我应该将自定义单元格的委托作为弱引用属性吗?
Should I make delegate of custom cell as a weakly referenced proprety?
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 如何保持对单元格的强引用?
那里发生了几件事。
使每个 ViewController 都符合 UITableViewDelegate 和 UITableViewDatasource 是不必要的,因为您已经拥有 UITableViewController 并且您可能无论如何都需要重写这些方法。您可能会在开发生命周期的某个时刻重复代码。
委托总是需要成为弱引用以避免循环引用。
去初始化过程:
当视图控制器弹出时。
然后调用 deinit 方法。
然后只有视图控制器持有的所有其他引用被清除。
parents deinit触发,child的deinit触发,然后遍历所有deinit,最后parent的deinit释放完成。
如果任何子项强引用父项。 parent 的 deinit 永远不会被调用,所有的去初始化过程都会停止。在我们的例子中,因为单元格强烈保留视图控制器。 ViewController 的 deinit 方法永远不会被调用。因此,保留周期。
这是对 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")
}
}
自定义单元格代码
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 如何保持对单元格的强引用?
那里发生了几件事。
使每个 ViewController 都符合 UITableViewDelegate 和 UITableViewDatasource 是不必要的,因为您已经拥有 UITableViewController 并且您可能无论如何都需要重写这些方法。您可能会在开发生命周期的某个时刻重复代码。
委托总是需要成为弱引用以避免循环引用。
去初始化过程:
当视图控制器弹出时。 然后调用 deinit 方法。
然后只有视图控制器持有的所有其他引用被清除。
parents deinit触发,child的deinit触发,然后遍历所有deinit,最后parent的deinit释放完成。
如果任何子项强引用父项。 parent 的 deinit 永远不会被调用,所有的去初始化过程都会停止。在我们的例子中,因为单元格强烈保留视图控制器。 ViewController 的 deinit 方法永远不会被调用。因此,保留周期。 这是对 retain cycle.
的很好解释