【问题标题】:Should I make delegate of custom cell as a weakly referenced proprety?我应该将自定义单元格的委托作为弱引用属性吗?
【发布时间】:2016-08-25 02:49:21
【问题描述】:

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")
    }
}

自定义单元代码

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

现在最大的问题是 ViewController 如何保持对单元格的强引用?

【问题讨论】:

  • 我认为真正的问题是单元格之前的一步:什么是具有强引用的@IBOutlet?如果是 ViewController,它如何在内部管理保留周期?
  • 再次更新了完整的 ViewController 代码。

标签: swift delegates retain-cycle


【解决方案1】:

那里发生了几件事。

  1. 使每个 ViewController 都符合 UITableViewDelegate 和 UITableViewDatasource 是不必要的,因为您已经拥有 UITableViewController 并且您可能无论如何都需要覆盖这些方法。您会在开发生命周期的某个阶段复制代码。

  2. 委托始终需要成为弱引用以避免保留循环。

【讨论】:

  • 还要注意,由于buttonTapped不传递self,所以不容易知道点击了哪个按钮。
  • @MatthewSeaman 你是对的。这很难说,但再说一遍......他可能无论如何都需要覆盖整个实现。
  • 我在这里展示的代码仅用于演示目的。请参阅上述更新。
  • 显然 tableView 持有对 ViewController 的强引用,而不管 @IBOutlet 是弱引用。这很有趣。
【解决方案2】:

去初始化过程:

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

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

Parents deinit 触发,child 的 deinit 触发,然后在遍历所有 deinit 之后,最后完成 parent 的释放。

如果任何孩子强烈引用父母。 parent 的 deinit 永远不会被调用,并且所有的 deinitialization 过程都会停止。在我们的例子中,因为 cell 强烈地保留视图控制器。 ViewController 的 deinit 方法永远不会被调用。因此保留周期。 这是retain cycle.的很好解释

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 2022-10-16
    • 1970-01-01
    相关资源
    最近更新 更多