Donghee Seo Donghee Seo - 5 months ago 39
iOS Question

Method collectionview(cellForItemAtIndexPath) is called many times when i rotate

I'm studying Swift. I have 2 questions.

Full source is here.
1. Why is collectionview(cellForItemAtIndexPath) called many times like this?

EDIT: What I want to know is why collectionview(cellForItemAtIndexPath) get called several times per one rotation event.
1) rotation method

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

print("4 self.collectionView.frame=\(self.collectionView.frame)")
print("4 size=\(size)")

self.collectionView.frame.size = size

let currentSize = self.collectionView.bounds.size
let offset = CGFloat(self.indexPathRow) * size.height
print("offset=\(offset)")
self.collectionView.setContentOffset(CGPointMake(0, offset), animated: true)
print("self.collectionView.contentOffset=\(self.collectionView.contentOffset)")

// Suppress the layout errors by invalidating the layout
self.collectionView.collectionViewLayout.invalidateLayout();


// Where is the best location of super? Top of this method or bottom?
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}


2) collectionview method

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

currentOffset = self.collectionView.contentOffset
print("currentOffset=\(currentOffset)")

//print("indexPath=\(indexPath.row)")
let frame = self.collectionView.frame

let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseCellIdentifier, forIndexPath: indexPath) as! MainCollectionViewCell

let imageName = dataArray[indexPath.row]
let image = UIImage(named: imageName)
cell.imageView.image = image
if (frame.size.width >= frame.size.height) {
cell.imageView.frame = frame
}
else {
cell.imageView.frame = CGRectMake(0, 0, frame.width*2, frame.height)
}
print("cell.imageView.frame=\(frame)")
print("cell.imageView.image=\(cell.imageView.image!.size)")

if (indexPath.row % 2 == 0) {
cell.backgroundColor = UIColor.orangeColor()
}
else {
cell.backgroundColor = UIColor.yellowColor()
}

currentIndex = Int(currentOffset.y / frame.size.height)
print("currentIndex=\(currentIndex)")
indexPathRow = indexPath.row

return cell
}



  1. I meet warning messages when I rotate from landscape to portrait. I don't want to see this warning, but I can't. Below is the log message when I rotate. And this message shows multiple called-method. (You can meet this log - Pass 12th cell in landscape then rotate to portrait.)



    4 self.collectionView.frame=(0.0, 0.0, 667.0, 375.0)
4 size=(375.0, 667.0)
2016-06-10 14:22:05.750 CollectionViewWithoutStoryboard[49615:2682527] the behavior of the UICollectionViewFlowLayout is not defined because:
2016-06-10 14:22:05.750 CollectionViewWithoutStoryboard[49615:2682527] the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
2016-06-10 14:22:05.751 CollectionViewWithoutStoryboard[49615:2682527] The relevant UICollectionViewFlowLayout instance is , and it is attached to ; layer = ; contentOffset: {0, 4875}; contentSize: {667, 7500}> collection view layout: .
2016-06-10 14:22:05.751 CollectionViewWithoutStoryboard[49615:2682527] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
offset=8671.0
self.collectionView.contentOffset=(0.0, 4729.0)
self.collectionView.frame=(0.0, 0.0, 375.0, 667.0)
currentOffset=(0.0, 4729.0)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=7
currentOffset=(0.0, 4729.0)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=7
self.collectionView.frame=(0.0, 0.0, 375.0, 667.0)
currentOffset=(0.0, 5449.0)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=8
currentOffset=(0.0, 6029.5)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=9
currentOffset=(0.0, 6717.0)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=10
currentOffset=(0.0, 7393.0)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=11
currentOffset=(0.0, 8218.5)
cell.imageView.frame=(0.0, 0.0, 375.0, 667.0)
cell.imageView.image=(1920.0, 804.0)
currentIndex=12

Answer

Check this question out

Answer detailing how cellForRowAtIndexPath works

The above answer details how cellForRowAtIndexPath works in a UITableView

cellForItemAtIndexPath in a UICollectionView is built around the same concepts. You can think of both these controls as optimized versions of UIScrollView. Since a TableView or CollectionView might contain several items, the controls reuse the views and when it's time to draw that particular cell, this method is called. Therefore do not think about these methods as initialisers but rather as drawing methods where you need to specify how your cell is going to look.

I hope this explanation helps!

Comments