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 拾取的主要内容,如果未能解决你的问题,请参考以下文章
SendMessage(hwnd, registeredmssghere, 0, 1) 已接收但未被其发送到的挂钩线程正确识别!