2014-11-24 4 views
0

У меня есть супер простое базовое приложение,необъяснимые утечки памяти стремительные IOS

только 1 ViewController с CollectionView

швы просачиваться мой 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 и назначить его в настройке

var collectionViewLayout : UICollectionViewFlowLayout? 
func setup() { 
    self.collectionViewLayout = UICollectionViewFlowLayout() 
    self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: self.collectionViewLayout!) 
    ... 

это не утечка .. но это не может быть решением?

ответ

2

Я ранее сталкивался с ошибкой Swift, связанной с загрузкой NIB, которая может вызвать инициализацию свойств дважды. Если я правильно помню, в некоторых случаях два одинаковых инициализатора могут быть вызваны в одном экземпляре объекта, в результате чего свойства экземпляра объекта будут инициализированы дважды, а утечка чего-либо была создана при первой инициализации. (Это было в ранней версии Swift с использованием NSWindowController в приложении Cocoa. Я не знаю, существует ли ошибка в текущей версии Swift.)

Это объясняет утечку, которую вы видите с вашим свойством collectionViewLayout, и почему он не течет при назначении свойства в setup().

Вы можете использовать инструменты, чтобы узнать, сколько создаются UICollectionViewFlowLayout экземпляры, или вы можете установить символическую точку останова в -[UICollectionViewFlowLayout init], чтобы увидеть, если он вызывается дважды во время ViewController инициализации.

В противном случае это может быть ложным положительным в детекторе утечки.

Чтобы обойти эту проблему, вы можете попробовать наиважнейшую init(coder:) и инициализировать свойство collectionViewLayout в этом методе:

required init(coder aDecoder: NSCoder) { 
    self.collectionViewLayout = UICollectionViewFlowLayout() 
    super.init(coder:aDecoder) 
} 

Однако, вы хотите, чтобы подтвердить, что этот инициализатор не вызываются дважды.

+0

Да, кажется, что мои точки останова дважды ударяют метод init, любое предложение о том, как исправить эту проблему? –

+1

похоже: http://stackoverflow.com/a/26310782/62009 помог мне, спасибо, указав мне в направлении двойной инициализации. –

0

Поскольку CollectionView имеет delegate и datasource, вы должны указать его как weak, чтобы избежать удержаний циклов (утечек).

Смежные вопросы