我有一个超级简单的基本应用程序,
只有1个带有collectionView的viewcontroller
它接缝泄漏我的collectionViewFlowLayout,我不知道为什么
Leaked Object # Address Size Responsible Library Responsible Frame
__NSDictionaryM 1 0x7fcc4ca31340 48 Bytes UIKit UICollectionViewLayoutCommonInit
__NSDictionaryM 1 0x7fcc4ca313a0 48 Bytes UIKit UICollectionViewLayoutCommonInit
__NSDictionaryI 1 0x7fcc4ca31570 64 Bytes UIKit UICollectionViewFlowLayoutCommonInit
__NSDictionaryM 1 0x7fcc4ca313d0 48 Bytes UIKit UICollectionViewLayoutCommonInit
UICollectionViewFlowLayout 1 0x7fcc4ca310c0 512 Bytes leak-application ObjectiveC.UICollectionViewFlowLayout.__allocating_init (ObjectiveC.UICollectionViewFlowLayout.Type)() -> ObjectiveC.UICollectionViewFlowLayout
__NSDictionaryM 1 0x7fcc4ca31370 48 Bytes UIKit UICollectionViewLayoutCommonInit
__NSDictionaryM 1 0x7fcc4ca31400 48 Bytes UIKit UICollectionViewLayoutCommonInit
NSMutableIndexSet 1 0x7fcc4ca314e0 48 Bytes UIKit UICollectionViewLayoutCommonInit
NSMutableIndexSet 1 0x7fcc4ca31470 48 Bytes UIKit UICollectionViewLayoutCommonInit
__NSDictionaryM 1 0x7fcc4ca2f290 48 Bytes UIKit UICollectionViewLayoutCommonInit
这是我的代码
class ParallaxCollectionViewCell: UICollectionViewCell {
let titleLabel = UILabel(frame: CGRectMake(0, 0, 100, 100))
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.addSubview(titleLabel)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var collectionView: UICollectionView?
let collectionViewLayout = UICollectionViewFlowLayout()
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
func setup() {
self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: self.collectionViewLayout)
self.view.addSubview(self.collectionView!)
self.collectionView?.delegate = self;
self.collectionView?.dataSource = self;
self.collectionView?.backgroundColor = UIColor.whiteColor()
self.collectionView?.registerClass(ParallaxCollectionViewCell.self, forCellWithReuseIdentifier: "identfifier")
self.collectionView?.reloadData()
}
override func viewDidLayoutSubviews() {
self.collectionView?.frame = self.view.bounds
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(CGRectGetWidth(self.view.bounds), 100)
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let parallaxCell = collectionView.dequeueReusableCellWithReuseIdentifier("identfifier", forIndexPath: indexPath) as ParallaxCollectionViewCell
parallaxCell.titleLabel.text = "test"
return parallaxCell
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
}
如果我将collectionViewLayout属性设为可选的var并在setup
中指定它var collectionViewLayout : UICollectionViewFlowLayout?
func setup() {
self.collectionViewLayout = UICollectionViewFlowLayout()
self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: self.collectionViewLayout!)
...
它没有泄漏..但这不是解决方案?
答案 0 :(得分:2)
我之前遇到过与NIB加载相关的Swift错误,可能导致属性被初始化两次。如果我没记错的话,在某些情况下,可以在同一个对象实例上调用两个不同的指定初始值设定项,导致对象的实例属性初始化两次,并且在第一次初始化期间实例化泄漏任何内容。 (那是在Cocoa应用程序中使用NSWindowController的早期Swift测试版。我不知道当前Swift版本中是否仍存在该bug。)
这可以解释您在collectionViewLayout
财产中看到的泄漏,以及在setup()
分配财产时它为什么不泄漏。
您可以使用Instruments查看创建了多少UICollectionViewFlowLayout
个实例,或者您可以在-[UICollectionViewFlowLayout init]
中设置符号断点,看看它是否在ViewController
期间被调用了两次初始化。
否则,它可能只是检漏仪中的误报。
要解决此问题,您可以尝试覆盖init(coder:)
并在该方法中初始化collectionViewLayout属性:
required init(coder aDecoder: NSCoder) {
self.collectionViewLayout = UICollectionViewFlowLayout()
super.init(coder:aDecoder)
}
但是,您要确认此初始值设定项未被调用两次。
答案 1 :(得分:1)
由于CollectionView
有delegate
和datasource
,您应该将其声明为weak
以避免保留周期(泄漏)。