Search code examples
iosswiftdeinit

Deinit not called where blocks used in swift 3.0


I have used blocks in cell for getting switch value but now my problem is that deinit not called where i used the blocks. it is completely working previously but in swift 3.0 it is not working.

My switch cell :

import UIKit

class CellSwitch: UITableViewCell {

    @IBOutlet weak var objSwitch: UISwitch!
    @IBOutlet weak var btnInfo: UIButton!
    @IBOutlet weak var lblTitle: UILabel!
    var blockSwitch_Change : ((_ isOn:Bool) -> Void)!
    var blockBtn_Clicked : (() -> Void)!

    override func awakeFromNib() {
        super.awakeFromNib()
        self.lblTitle.font = Font.init(Font.FontType.custom(Font.FontName.NotoSans_Regular), size: Font.FontSize.standard(Font.StandardSize.Regular)).instance
        // Initialization code
    }
    //MARK:- switch object change
    @IBAction func switch_ValChanged(_ obj:UISwitch){
        self.blockSwitch_Change?(obj.isOn)
    }

    //MARK:-  button clicked
    @IBAction func btnInfo_Clicked(_ sender: UIButton) {
        self.blockBtn_Clicked?()
    }
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

Uses of this cell

let cell = tableView.dequeueReusableCell(withIdentifier: CellSwitch.identifier) as? CellSwitch
                cell?.lblTitle.textColor = Color.custom(hexString: objModel.titleLblColor, alpha: 1.0).value
                cell?.lblTitle.text = objModel.strTitle
                cell?.objSwitch.isOn = objModel.isOn
                cell?.btnInfo.isHidden = !objModel.isInfoBtn
                cell?.blockBtn_Clicked = { 
                   print("button clicked")
                }
                cell?.blockSwitch_Change = { (isOn) in
                    print("switch value changed \(isOn)")
                }
                if objModel.isEnable == false
                {
                    cell?.isUserInteractionEnabled = false
                    cell?.contentView.alpha = 0.5
                }
                else
                {
                    cell?.isUserInteractionEnabled = true
                    cell?.contentView.alpha = 1.0
                }
                return cell!

Also if i comment this two blocks then my deinit will called.


Solution

  • It sounds like you are creating a retain cycle by referencing the view controller strongly inside the blocks. Instead you should create a weak reference to the vc to use. This is my preferred method

    cell?.blockBtn_Clicked = { [weak self]
        print("button clicked")
        self?.viewModel.//do something
    }
    cell?.blockSwitch_Change = { [weak self] (isOn) in
        print("switch value changed \(isOn)")
        self?.viewModel.//do something
    }
    

    The [weak self] portion will pass a weak reference of self into the block, although note this reference is now an optional. You can then use optional chaining or unwrap it after that.