移除NSTableView列时如何让绑定的CMYK对象自动执行deinit
解决移除NSTableView列时绑定对象未释放的问题
我来帮你梳理下这个问题的核心原因,以及对应的解决办法:
问题根源
你已经从colors数组里移除了CMYK对象,也删除了对应的表格列,但对象的deinit没触发,说明还有其他地方持有该对象的强引用。这里最可能的是:NSTableView的列(或者它内部的cell/缓存)还保留着对CMYK对象的强引用,哪怕你移除了列,这个引用没被及时切断,ARC就无法释放对象。
解决方案
我们需要在移除列之前,主动切断表格列和对象之间的强引用,具体修改你的removeTableColumn方法即可:
@IBAction func removeTableColumn(_ sender: Any) { guard let column = tableView.tableColumns.last, let idx = tableView.tableColumns.firstIndex(of: column) else { return } // 关键步骤:先清空该列对应行的objectValue,切断表格对对象的强引用 tableView.setObjectValue(nil, for: column, row: 0) // 再从数据源数组移除对象 colors.remove(at: idx) // 移除表格列 tableView.removeTableColumn(column) tableView.reloadData() }
额外优化建议
你的数据源实现用硬编码的identifier判断索引,扩展性很差,建议改成动态匹配索引的方式,后续增减列都不用修改这部分代码:
extension ViewController: NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { return 1 } func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { guard let colIdStr = tableColumn?.identifier.rawValue, let colIndex = Int(colIdStr), colIndex < colors.count else { return nil } return colors[colIndex] } }
原理说明
当你调用tableView.setObjectValue(nil, for: column, row: 0)时,会让NSTableView主动释放对该列对应行对象的强引用。此时colors数组也移除了对象,没有其他强引用存在,ARC就会自动调用CMYK对象的deinit方法,你就能在控制台看到对应的打印信息了。
如果之后还是没触发deinit,可以检查下是否有其他地方(比如闭包、全局变量、其他视图组件)持有了CMYK对象的强引用,逐步排查即可。
内容的提问来源于stack exchange,提问作者CocoaUser
相关产品推荐
相关产品推荐

