1
votes

I want to manage memory so I want to deinit the UIview when leaving ViewController.
And I try to use keyword "weak" and I get crash because my chatkeyboard is nil.
I dont know why making it crash.
Thanks.

class ChatKeyboard: UIView {

var buttonMic:UIButton = { ()->UIButton in
    let ui:UIButton = GeneratorButton()
    return ui
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    print("===) ChatKeyboard init.")
    translatesAutoresizingMaskIntoConstraints = false
    loadContent()
    loadConstrain()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

deinit {
    print("===) ChatKeyboard deinit.")
}

func loadContent() {

backgroundColor = UIColor.white
addSubview(buttonMic)
}

func loadConstrain() {

buttonMic.snp.makeConstraints { (make) -> Void in
           make.left.equalTo(micLeftPadding)
           make.top.equalTo(micTopPadding)
           make.width.equalTo(UIScreen.main.bounds.width*0.0581)
           make.height.equalTo(UIScreen.main.bounds.height*0.045)
}
}
}


class ChatroomViewController: UIViewController{

weak var chatKeyboard:ChatKeyboard?

override func viewDidLoad() {
    super.viewDidLoad()

    chatKeyboard = ChatKeyboard(frame: CGRect(x: 0, y: 0, width: 300, height: 44))
}
}

I set breakpoint at "chatKeyboard = ChatKeyboard(frame: CGRect(x: 0, y: 0, width: 300, height: 44))"and then my log print:

===) ChatKeyboard init.
===) ChatKeyboard deinit.
3

3 Answers

3
votes

A weak variable will be destroyed as soon as there are no strong references to it.

If you're creating a view and assigning it directly to a weak variable, it will be destroyed immediately. Weak IBOutlets work because they are added to a superview (creating a strong reference) before they are assigned to the variable. You can achieve this by using a local variable before assigning to your property:

let keyboard = ChatKeyboard(...)
view.addSubview(keyboard)
chatKeyboard = keyboard

However, there is no harm in your view controller having strong references to views it cares about, as long as those views don't also have strong references back to the view controller. They'll get destroyed when the view controller is destroyed.

1
votes

Reason is you have declared your chatKeyBoard as

weak var chatKeyboard:ChatKeyboard?

Which means your viewController will not hold any strong reference to the view you load. Hence reference count of the view will not vary.

In your viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    chatKeyboard = ChatKeyboard(frame: CGRect(x: 0, y: 0, width: 300, height: 44))
}

You instantiate the view but because view was weakly held as soon as the control goes out of the scope of viewDidLoad ARC released the view.

If you want your view to be accessible even after viewDidLoad called declare a strong a refrence

var chatKeyboard:ChatKeyboard?

Hope it helps

0
votes

In a class or structure, do not use keyword "weak" to describe the property which you will init in the same class or structure.