High Sierra 中的 NSCollectionView 内存泄漏?
NSCollectionView memory leak in High Sierra?
我注意到通过 Instruments 在 NSCollectionView 中存在内存泄漏。当我找到代码时,它显示了下面的特定行:
collectionView.makeItem(withIdentifier: identifier, for: indexPath) as? DisplayableCellProtocol
然后我在内存调试器Xcode中查看,发现有一些未引用的项目导致了泄漏。不过,并非makeItem
创建的所有项目都泄漏,有些是正常的,但有些甚至没有显示。
Managed正常未泄露的项目是这样的图
而泄露出来的是这样的(没有任何联系):
这正常吗,有没有人遇到同样的问题?有谁知道如何正确解决这个问题?这与使用 xib 设计项目视图有什么关系吗?
下面是一些可能有助于理解情况的代码:
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let data = datasource[indexPath.item]
let identifier: String = "ServiceCell"
// Next line is where the leak occurs
guard let cell = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: identifier), for: indexPath) as? ServiceCell else {
return ServiceCell(nibName: NSNib.Name("ServiceCell.xib"), bundle: Bundle.main)
}
cell.iconView.image = data.icon
cell.serviceLabel.stringValue = data.name
cell.introLabel.stringValue = data.content
cell.highlighted = false
return cell
}
ServiceCell的定义是:
class ServiceCell: NSCollectionViewItem {
@IBOutlet weak var iconView: NSImageView!
@IBOutlet weak var serviceLabel: NSTextField!
@IBOutlet weak var cmdLabel: NSTextField!
@IBOutlet weak var introLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
不确定代码在这里是否有帮助。自己的代码有没有BUG,我也试过,目前还没有发现。
同时,我发现了很多其他漏洞,其中大部分指向makeItem
行
更新:我又看了一遍。所以每次它都会使实际需要的物品数量翻倍。例如,我需要 2 个单元格,它会创建 4 个而不是 2 个,其中两个是泄漏的单元格。有什么想法吗?
终于解决了。创建xib文件时,创建继承自NSCollectionViewItem
的class时,xib中File Owner的class设置为subclass之前默认创建。当我们在xib中添加自定义对象时,这个需要设置为空。
如果您的 delegate
和 dataSource
(弱?)设置为 NSCollectionView 本身,我假设您会遇到此问题。我在 MacOSX 10.14.6 上有这个有点可疑的设置。
随着代表 so-wired 的加入,我疑惑地通过为 willDisplayItem
and didEndDisplayingItem
引入空存根来“解决”了这个问题。这样,内存泄漏就消失了。
我的 collection 查看内容是 48 项;没有这些存根,第一个 return 来自 itemForRepresentedObjectAtIndexPath
(which called makeItemWithIdentifier
) beach-balled 我的应用程序内存使用率飙升。
我现在正在将此 collection 视图重新定位到 NSViewController
以避免这些恶作剧。
我注意到通过 Instruments 在 NSCollectionView 中存在内存泄漏。当我找到代码时,它显示了下面的特定行:
collectionView.makeItem(withIdentifier: identifier, for: indexPath) as? DisplayableCellProtocol
然后我在内存调试器Xcode中查看,发现有一些未引用的项目导致了泄漏。不过,并非makeItem
创建的所有项目都泄漏,有些是正常的,但有些甚至没有显示。
Managed正常未泄露的项目是这样的图
而泄露出来的是这样的(没有任何联系):
这正常吗,有没有人遇到同样的问题?有谁知道如何正确解决这个问题?这与使用 xib 设计项目视图有什么关系吗?
下面是一些可能有助于理解情况的代码:
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let data = datasource[indexPath.item]
let identifier: String = "ServiceCell"
// Next line is where the leak occurs
guard let cell = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: identifier), for: indexPath) as? ServiceCell else {
return ServiceCell(nibName: NSNib.Name("ServiceCell.xib"), bundle: Bundle.main)
}
cell.iconView.image = data.icon
cell.serviceLabel.stringValue = data.name
cell.introLabel.stringValue = data.content
cell.highlighted = false
return cell
}
ServiceCell的定义是:
class ServiceCell: NSCollectionViewItem {
@IBOutlet weak var iconView: NSImageView!
@IBOutlet weak var serviceLabel: NSTextField!
@IBOutlet weak var cmdLabel: NSTextField!
@IBOutlet weak var introLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
}
不确定代码在这里是否有帮助。自己的代码有没有BUG,我也试过,目前还没有发现。
同时,我发现了很多其他漏洞,其中大部分指向makeItem
行
更新:我又看了一遍。所以每次它都会使实际需要的物品数量翻倍。例如,我需要 2 个单元格,它会创建 4 个而不是 2 个,其中两个是泄漏的单元格。有什么想法吗?
终于解决了。创建xib文件时,创建继承自NSCollectionViewItem
的class时,xib中File Owner的class设置为subclass之前默认创建。当我们在xib中添加自定义对象时,这个需要设置为空。
如果您的 delegate
和 dataSource
(弱?)设置为 NSCollectionView 本身,我假设您会遇到此问题。我在 MacOSX 10.14.6 上有这个有点可疑的设置。
随着代表 so-wired 的加入,我疑惑地通过为 willDisplayItem
and didEndDisplayingItem
引入空存根来“解决”了这个问题。这样,内存泄漏就消失了。
我的 collection 查看内容是 48 项;没有这些存根,第一个 return 来自 itemForRepresentedObjectAtIndexPath
(which called makeItemWithIdentifier
) beach-balled 我的应用程序内存使用率飙升。
我现在正在将此 collection 视图重新定位到 NSViewController
以避免这些恶作剧。