Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionViewController's layout ownership (self.collectionView.collectionViewLayout vs. self.collectionViewLayout)

I have a UICollectionViewController managing a collection view that uses different layouts for different app states. I'm using -setCollectionViewLayout:animated: to transition between the different layouts. I'm having a bad access error, and it would help immensely to know what actually owns (e.g. keeps a strong reference to) the collection view's current layout.

After calling -setCollectionViewLayout:animated:, I've noticed the following (where self is the UICollectionViewController):

  • self.collectionView.collectionViewLayout returns the new layout.
  • self.collectionViewLayout still returns the old layout.

This led me to check the UICollectionView Class Reference, which explains this behavior:

collectionViewLayout

The layout object used to initialize the collection view controller. (read-only)

@property (nonatomic,readonly) UICollectionViewLayout *collectionViewLayout

Discussion
This property contains the layout object you passed to the initWithCollectionViewLayout: method. The layout object in this property is not updated to reflect changes to the collection view itself. You can use this property to refer to the layout object you originally configured the collection view to use.

Okay. So self.collectionViewLayout is a weak reference (or is it?) to the initial layout and self.collectionView.collectionViewLayout is a strong reference to the current layout.

To confirm this, I took a dive into the debugger, but wasn't able to find the actual UICollectionView supposedly owned by the UICollectionViewController. Instead, the collection view controller's _view variable was an instance of UICollectionViewControllerWrapperView. Whaaaat?

This whole experience left me with the following questions:

  1. Where is the actual UICollectionView stored in a UICollectionViewController?
  2. Does self.collectionViewLayout keep a strong reference to the initial layout?
like image 232
George WS Avatar asked Sep 23 '13 20:09

George WS


People also ask

What is uicollectionviewlayout?

This component allows for very simple grid layout creation and it even allows you to dynamically change layouts with beautiful animations. UICollectionView becomes even more powerful and flexible if you create your own layout by subclassing UICollectionViewLayout.

How do I add a collection view to a view controller?

The first thing you should do is open up the Main.storyboard and drag a UICollectionView out to your View Controller. When you've done this give the collection view a white background color and add constraints to it so it will fit your view nicely.

How do I display cat images in a uicollectionview?

Select the UICollectionView, hold ctrl and drag over to the code editor to create an outlet for the UICollectionView. I named mine "collectionView". That's all the setup we need for now. To display our cat images we need to have a UICollectionViewCell with an image inside of it.

How do I align a collection view to the status bar?

When you've done this give the collection view a white background color and add constraints to it so it will fit your view nicely. If you're unsure how to do this, size the collection view so that it touches the left, bottom and right edges of the view and it should be aligned underneath the status bar.


1 Answers

Alright, I've already answered my first question: UICollectionViewControllerWrapperView has an ivar called _subviewCache, which is a mutable array containing the actual UICollectionView at index 0. Weird.

However, I would still love an answer to my second question. It seems to me like the collection view controller is not keeping a strong reference to the initial layout because its collectionViewLayout (initial layout) property is readonly, and I can't find any reference to a collection view layout when inspecting the collection view controller in the variables view of the debugger. Yet, if this is the case, how is it holding onto the initial layout even after the collection view's strong reference to the initial layout has been replaced with a strong reference to a different layout?


Update: It turns out the bad-access crash I was seeing was actually caused by a slightly different issue that has to do with UIDynamicAnimator's ownership of the layout. This is almost definitely a bug in Apple's code, and I've filed a radar which you can read here (duplications welcome!):

http://www.openradar.me/15062440

That said, none of this technically addresses my second question. It's no longer relevant to me or to my work, but I'd still welcome and upvote any real answers, even if they'd be purely academic at this point.

like image 106
George WS Avatar answered Sep 29 '22 17:09

George WS