I have a super simple basic application,
just 1 viewcontroller with a collectionView
It seams to leak my collectionViewFlowLayout, and i don't know why
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
this is my code
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
}
}
If i make the collectionViewLayout property an optional var and assign it in setup
var collectionViewLayout : UICollectionViewFlowLayout?
func setup() {
self.collectionViewLayout = UICollectionViewFlowLayout()
self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: self.collectionViewLayout!)
...
it doesn't leak .. but that cannot be the solution ?
I've previously encountered a Swift bug related to NIB loading that can cause properties to be initialized twice. If I recall correctly, in some cases two different designated initializers could be called on the same object instance, causing the object's instance properties to be initialized twice and leaking anything was instantiated during the first initialization. (That was in an early Swift beta using NSWindowController in a Cocoa application. I don't know if the bug still exists in the current Swift version.)
That would explain the leak you're seeing with your collectionViewLayout
property, and why it doesn't leak when you assign the property in setup()
.
You can use Instruments to see how many UICollectionViewFlowLayout
instances are created, or you can set a symbolic breakpoint in -[UICollectionViewFlowLayout init]
to see if it's called twice during your ViewController
initialization.
Otherwise, it could just be a false positive in the leak detector.
To work around the problem, you can try overriding init(coder:)
and initialize your collectionViewLayout property in that method:
required init(coder aDecoder: NSCoder) {
self.collectionViewLayout = UICollectionViewFlowLayout()
super.init(coder:aDecoder)
}
However, you'll want to confirm that this initializer is not called twice.