Search code examples
objective-cios7uicollectionviewautolayoutuicollectionreusableview

Auto Layout in UICollectionReusableView not working on iOS7 but working on iOS8


I'm working on an app compatible with iOS8 and iOS7.

I have made a collection view header by subclassing UICollectionReusableView and the UI has been made with Interface Builder. Here an schema of the header's interface :

---------------------------- | | | A | | | |---------------------------| | | | B | | | |---------------------------| | | | C | | | ----------------------------

The problem

A, B and C views are link by Leading and Trailing on the super view (UICollectionReusableView) and it work fine on iOS8. But on iOS7 when the view is layout to have the reference size (768pt of width), the subviews have a width of 1216pt (it should be the same width as the superview : 768pt)...

What I've found

Here are the constraints on the UICollectionReusableView :

<NSLayoutConstraint:0x7c4196c0 UIView:A.top == HEADER:0x7be52ff0.top>,
<NSLayoutConstraint:0x7c4196f0 HEADER:0x7be52ff0.trailing == UIView:A.trailing>,
<NSLayoutConstraint:0x7c419720 UIView:A.leading == HEADER:0x7be52ff0.leading>,
<NSLayoutConstraint:0x7c4197b0 HEADER:0x7be52ff0.trailing == UIView:B.trailing>,
<NSLayoutConstraint:0x7c419810 UIView:B.top == UIView:A.bottom>,
<NSLayoutConstraint:0x7c419840 UIView:B.leading == HEADER:0x7be52ff0.leading>,
<NSLayoutConstraint:0x7c419870 UIView:C.top == UIView:B.bottom>,
<NSLayoutConstraint:0x7c4198a0 UIView:C.leading == HEADER:0x7be52ff0.leading>,
<NSLayoutConstraint:0x7c4198d0 HEADER:0x7be52ff0.trailing == UIView:C.trailing>,
<NSLayoutConstraint:0x7c419900 HEADER:0x7be52ff0.bottom == UIView:C.bottom>,
<NSLayoutConstraint:0x7be98df0 HEADER:0x7be52ff0.width == 768>,
<NSLayoutConstraint:0x7be98e20 HEADER:0x7be52ff0.height == 512>

And here is what happen in the overriding of layoutSubviews in my UICollectionReusableView by calling [self recursiveDescription] in the console :

Before calling [super layoutSubviews]

<HEADER: 0x7be52ff0; baseClass = UICollectionReusableView; frame = (0 0; 768 512); clipsToBounds = YES; layer = <CALayer: 0x7be87300>>
   | <UIView: A; frame = (0 0; 320 360); autoresize = RM+BM; layer = <CALayer: 0x7be53190>>
   |    | ...
   | <UIView: B; frame = (0 360; 320 96); autoresize = RM+BM; layer = <CALayer: 0x7be6bc50>>
   |    | ...
   | <UIView: C; frame = (0 456; 320 56); autoresize = RM+BM; layer = <CALayer: 0x7c417360>>
   |    | ...

After calling [super layoutSubviews]

<HEADER: 0x7be52ff0; baseClass = UICollectionReusableView; frame = (0 0; 768 512); clipsToBounds = YES; layer = <CALayer: 0x7be87300>>
   | <UIView: A; frame = (0 0; 1216 360); autoresize = RM+BM; layer = <CALayer: 0x7be53190>>
   |    | ...
   | <UIView: B; frame = (0 360; 1216 96); autoresize = RM+BM; layer = <CALayer: 0x7be6bc50>>
   |    | ...
   | <UIView: C; frame = (0 456; 1216 56); autoresize = RM+BM; layer = <CALayer: 0x7c417360>>
   |    | ...

Attempts

I've tried to set leading and trailing constants Relative to margin which is not helping.

I've also tried to change manually the frames of A, B and C after the call of [super layoutSubviews] and call setNeedLayout on these views. But as I expected it crash the app.

Question

I'm having some hard time to find why this is happening since subviews inside A, B and C views are not trying to expend their superviews.

Is there some debugging techniques that can help me to identify the source of this bug ??

Thank you for your help !


Solution

  • After some hours I've found by chance the origin of the bug.

    My UICollectionReusableView was calling [self layoutIfNeeded] after everything has been filled with my model object, and I was calling it again in the Controller after data has been set. So I've remove the call that is made inside the UICollectionReusableView and it works fine now on iOS7. But I still don't understand why it does that with multiple calls to layoutIfNeeded...