我应该将自定义单元格的委托作为弱引用的属性吗?

时间:2016-08-25 02:49:21

标签: swift delegates retain-cycle

ViewController代码

class ViewController: UIViewController {
    deinit {
        print("ViewController deinitialised")
    }

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        self.tableView.dataSource = self
    }

    func didTapBlue() {

    }
}

extension ViewController: UITableViewDataSource, CustomCellDelegate {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("myCell") as! CustomCell
        cell.delegate =  self
        cell.textLabel!.text = "\(indexPath.row)"
        return cell
    }

    func buttonTapped() {
        print("Button tapped")
    }
}

CustomCell代码

class CustomCell: UITableViewCell {
    deinit {
        print("Cell deinitialised")
    }

    var delegate: CustomCellDelegate! //When protocol Type is A
    // weak prefix when protocol Type is B
    // weak var delegate: CustomCellDelegate!

    @IBAction func buttonClickAction(sender: AnyObject) {
        if let del = self.delegate {
            del.buttonTapped()
        }
    }
}

协议类型A

protocol CustomCellDelegate{
    func buttonTapped()
}

协议类型B

protocol CustomCellDelegate: class {
    func buttonTapped()
}

我很困惑在Cell和ViewController之间传递消息的实现委托模式的适当方法是什么。我知道如果两个对象强烈地保持彼此的引用,那么将会有一个保留周期,它们将不会在应用程序生命周期中被释放。

在上面的代码中,ViewController似乎没有Cell的引用。因此,我认为如果我使用类型A的协议并在单元格中保留ViewController的强引用并不重要。

但如果我将委托属性声明为弱引用属性,我的代码会更安全吗?它的含义是什么?

更新

事实证明,即使ViewController没有直接引用cell&即使TableView的引用很弱,ViewController也会以某种方式保持对单元格的强引用。当我遵循方法A时,即没有声明委托是弱引用。 Cell和ViewController中的deinit方法永远不会被调用。我也检查了仪器。如果我没有将委托声明为弱,那么持久保留计数会不断增加。

enter image description here

现在最大的问题是ViewController如何保持对细胞的强引用?

2 个答案:

答案 0 :(得分:1)

那里有几件事。

  1. 让每个ViewController都符合UITableViewDelegate和UITableViewDatasource是不必要的,因为你已经有了UITableViewController,你可能还需要覆盖这些方法。您将在开发生命周期的某个时刻复制代码。

  2. 委托总是需要作为弱引用来避免保留周期。

答案 1 :(得分:0)

取消初始化流程:

弹出视图控制器时。 然后调用deinit方法。

然后只清除视图控制器所持有的所有其他引用。

父母去掉触发器,孩子的deinit触发器然后遍历所有deinit然后最终完成父母的释放。

如果任何一个孩子强烈引用父母。父的deinit永远不会被调用,所有的deinitialization进程都会停止。在我们的例子中,由于单元格强烈保留视图控制器。 ViewController的deinit方法永远不会被调用。因此保留周期。 以下是retain cycle.

的绝佳解释