UITableViewCell 强引用周期,但未被 Instruments 中的 Leaks 拾取

Posted

技术标签:

【中文标题】UITableViewCell 强引用周期,但未被 Instruments 中的 Leaks 拾取【英文标题】:UITableViewCell strong reference cycle, but not being picked up by Leaks in Instruments 【发布时间】:2020-08-01 22:30:54 【问题描述】:

我正在使用自定义 UITableViewCells 填充 UITableView,每个 UITableViewCells 中都有一个按钮。为了检查是否按下了按钮,我使用了委托协议模式。这是我的实现:

protocol MyTableViewCellDelegate 
    func didPressButtonInTableView(for indexPath: IndexPath)


class MyTableViewCell: UITableViewCell 

    lazy var indexPath = (self.superview?.superview as! UITableView).indexPath(for: self)
    var delegate: MyTableViewCellDelegate!

    @IBAction func buttonPressed(_ sender: Any) 
        self.delegate.didPressButtonInTableView(for: self.indexPath!)
    



在阅读了一些关于内存管理的内容后,我意识到有时,由于“强引用循环”,持有对父类的引用的子类的实例不会被释放,因为父类和子类都持有互相强烈的引用。我们必须使用weak 关键字来定义一个弱关系,当父类被释放时,子类也会被释放。

所以,我意识到使用委托持有对 UITableView(父类)的强引用。运行一些测试,比如检查 Xcode 调试器中的内存使用情况并在子类中使用 deinit,我意识到这些表视图单元格没有被释放。将协议更改为使用AnyObject,然后将委托设置为weak 解决了该问题。再次运行时,内存使用量并没有持续增加,当我转到不同的视图时,deinit 被调用。

运行 Leaks in Instruments 中的两个版本的代码,在第一种情况下没有内存泄漏,但是,每次加载表视图时,内存都会显着增加。

我的问题是,为什么这没有在 Instruments 中标记为内存泄漏,因为子类使用委托持有对父类的强引用?这与导致 Instruments 捕获泄漏的传统父子字符串引用有什么区别?

【问题讨论】:

【参考方案1】:

那是因为 tableView 重用了单元格。由于 tableview 单元格被重用,它们往往仅在 tableview 本身被取消初始化时才会被取消初始化。因为即使它们现在不被使用,tableview 也会让它们保持活动状态,以防需要重用。

【讨论】:

感谢您的回答。当相应的 TableViewController 被解除时,tableView 是否会被取消?即使在关闭表格视图控制器后,我的表格视图单元格也没有被取消。 通常它会在tableView deinit之后立即deinit,如果不是,也许你会做一个retain cycle

以上是关于UITableViewCell 强引用周期,但未被 Instruments 中的 Leaks 拾取的主要内容,如果未能解决你的问题,请参考以下文章

TCP 套接字关闭但未被进程检测到

强引用strong和弱引用weak的定义

如何模拟在同一文件中定义但未被测试方法导入的函数?

SendMessage(hwnd, registeredmssghere, 0, 1) 已接收但未被其发送到的挂钩线程正确识别!

虚拟机四种引用类型和对象的生命周期

虚拟机四种引用类型和对象的生命周期