Donghee Seo
Donghee Seo

Reputation: 43

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

Upvotes: 0

Views: 1455

Answers (1)

Rajeev Bhatia
Rajeev Bhatia

Reputation: 2994

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!

Upvotes: 3

Related Questions