Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionViewCell layout issues iOS9

Since my move to the new iOS9 and Xcode 7 I have stumbled upon an issue with one of the UICollectionView in my app.

Apparently, the UICollectionView doesn't seem to update the UICollectionViewCell layout and constraints properly, only until it is reused.

Pictures speak better than words -- this is how it looks like when the UIViewController is first seen: enter image description here

However this isn't the correct layout, and easily enough when I swipe the UICollectionView horizontally to the left, I get the right layout of the newly appeared cells: enter image description here

When I swipe back, the old cells that weren't correct, are now reused and look good.

Now, as it was prior to upgrading to iOS9 and Xcode 7, my wanted effect is that the cells have the correct layout even when first appearing.

For your convenience, here are more details on how the UICollectionView is set up and it's constraints in the XIB: enter image description here

In the code, it is pretty standard:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell : MatchmakersCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionCell", forIndexPath: indexPath) as! MatchmakersCollectionViewCell

    cell.imageView.backgroundColor = UIColor.lightGrayColor()
    cell.bottomName.text = "StackOverflow"

    return cell
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.matchmakers.count
}

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

And every time I updated the datasource (self.matchmakers), I called self.collectionView.reloadData()

One last thing I had noticed which was very strange, when debugging with Xcode the debug view hierarchy, the UICollectionViewCell never presented the subviews properly and just gave me a default UIView in their stead: enter image description here

like image 988
Yarneo Avatar asked Sep 17 '15 13:09

Yarneo


Video Answer


3 Answers

To solve this problem:

  1. Creat your custom UICollectionViewCell using Nib(.xib) files.

  2. In your custom UICollectionViewCell ,override didMoveToSuperView() method to add this

    self.setNeedLayout()

    self.layoutIfNeeded()

3.In your UIViewController viewDidLoad() method

self.collectionView.registerNib(UINib(nibName: "yourNibName", bundle: nil), forCellWithReuseIdentifier: "Cell")

--------update 20150923

just need step 2, override didMoveToSuperView method to add

self.setNeedLayout()

self.layoutIfNeeded()

in your custom UICollectionViewCell class.

Thanks @macayer

like image 171
zihao rong Avatar answered Sep 22 '22 12:09

zihao rong


I didn't have to create my own XIB for my cell, as long as I have my custom cell and have it linked into my storyboard, I just added those line in (MyCustomCollectionViewCell.m):

- (void)didMoveToSuperview{
    [super didMoveToSuperview];

    [self setNeedsLayout];
    [self layoutIfNeeded];
}
like image 33
Marc Avatar answered Sep 18 '22 12:09

Marc


I had same bug in iOS9 too. Perhaps you've found that it's all ok after you reloaded the collection view. So my solution: set a timer for iOS9 to reload the cells.

if #available(iOS 9, *) {
   self.refreshTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("refreshDataTimer"), userInfo: nil, repeats: true)
}

And reload them :

func refreshDataTimer(){

    self.collectionView?.reloadData()

}

Even though this solution is little stupid but it works in few lines.

or you can reload each cell :

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

     .... 


    self.collectionView?.reloadItemsAtIndexPaths([indexPath])
    return cell
}

But it's inefficient.

like image 33
Joey Wong Avatar answered Sep 18 '22 12:09

Joey Wong