【问题标题】:Deinit not called where blocks used in swift 3.0在 swift 3.0 中使用的块中没有调用 Deinit
【发布时间】:2018-12-18 03:24:54
【问题描述】:

我在单元格中使用块来获取开关值,但现在我的问题是在我使用块的地方没有调用 deinit。它以前完全可以工作,但在 swift 3.0 中它不工作。

我的开关单元:

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
    }

}

此单元格的用途

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!

另外,如果我评论这两个块,那么我的 deinit 将被调用。

【问题讨论】:

  • 尝试将它们都设置为weak 引用。
  • 当您看到问题时,您在块中始终拥有的那些打印语句是您实际使用的代码吗?
  • @AidanMalone 不,我不能分享实际代码,这就是我临时放置打印语句的原因
  • @RakeshaShastri 可以提供代码吗?
  • 好的,块内的代码是否引用了单元格本身?

标签: ios swift deinit


【解决方案1】:

听起来您正在通过在块内强烈引用视图控制器来创建保留周期。相反,您应该创建对要使用的 vc 的弱引用。这是我的首选方法

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
}

[weak self] 部分会将 self 的弱引用传递到块中,但请注意此引用现在是可选的。然后,您可以使用可选链接或在此之后解包。

【讨论】:

  • 作为替代方案,您也可以使用 [unowned self]。这也将创建一个弱引用,但它不是可选的(在传递到块之前它将被隐式解包)。如果您不确定的 weak 通常更安全,因为它可以防止潜在的崩溃,但值得考虑的是,您可能不希望应用程序在调用此块且视图控制器已从内存中删除的情况下继续执行。跨度>
猜你喜欢
  • 2015-10-21
  • 2019-09-26
  • 1970-01-01
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-11
  • 2015-08-25
相关资源
最近更新 更多