我对Swift内存管理有些困惑。我了解,如果removeFromSuperview
为0,retainCount
会释放该视图并使它符合垃圾回收的条件。但是,在跟踪CFGetRetainCount(myView)
之后,我不确定retainCount
的计算方式以及如何正确确保该视图在调用removeFromSuperview之后将完全释放。
这就是我为一个简单的UILabel得到的。代码:
let myLabel = UILabel()
print("After creation")
print(CFGetRetainCount(myLabel))
myLabel.frame = CGRect(x: 0, y: 0, width: view.frame.width - 40, height: 60)
print("After frame set")
print(CFGetRetainCount(myLabel))
myLabel.text = "Lorem ipsum"
myMainView.addSubview(myLabel)
print("After added to superview")
print(CFGetRetainCount(myLabel))
let otherLabel = UILabel()
otherLabel.frame = CGRect(x: 0, y: myLabel.frame.maxY + 20, width: view.frame.width - 100, height: 60)
print("After referenced to position other view")
print(CFGetRetainCount(myLabel))
myLabel.removeFromSuperview()
print("After removed from superview")
print(CFGetRetainCount(myLabel))
控制台:
After creation
3
After frame set
3
After added to superview
4
After referenced to position other view
4
After removed from superview
3
这使我提出了几个问题:
1)我知道CFGetRetainCount包含弱引用,但是在刚创建UILabel后3如何?
2)当我以后不需要它们时,我要在没有类范围引用的函数内添加视图(我也可以添加gestureRecognizers),并在删除包含视图之前使用以下方法删除它们:
myMainView.subviews.forEach({
$0.removeFromSuperview()
})
这被认为是好的做法吗?手势识别器会阻止释放内存吗?
3)创建视图时,如何确保当计数已经为3时释放内存?
我想念什么?
DonMag上面共享的链接说明了为什么不应该使用keepCount的原因。ARC句柄为您保留计数。您需要担心的是保留周期。您上面提到的任何操作都不会创建保留周期,因此您应该相信编译器会从内存中删除该标签,只要该标签不再在任何地方被引用即可。发生保留周期的常见用例是引用自身和其他对象的委托和块。
因此,对于那些到这里结束并想知道同一件事的人,CFGetRetainCount返回的结果不可靠,如here所指出。
为了确保在使用自定义类时释放了内存,您可以在类内部进行调用并进行测试
deinit {
print("Memory deallocated")
}
如果未保留对象,则会自动调用上述方法。在此处查看文档:https://docs.swift.org/swift-book/LanguageGuide/Deinitialization.html
[其他泄漏可以使用仪器(在Xcode中:产品>配置文件>泄漏)或使用调试内存图工具进行测试
此处有更多说明:https://www.youtube.com/watch?v=1LnipXiSrSM
所以答案如下:
1 + 3)不要使用CFGetRetainCount。请参阅上面的说明。
2)这似乎工作正常,并且在我测试应用程序时释放了内存。