Xcode6, iOS8 and (void)layoutSubviews
Asked Answered
H

3

7

I have custom UILabel which works fine on iOS6 and iOS7. But on iOS8 this label's (void)layoutSubviews method never get called. I create this label with initWithFrame, so this method should be called - and it's called on another iOS versions. What happens with autoLayout system in iOS8?

Housetop answered 1/7, 2014 at 12:42 Comment(4)
The issue is even worse, as also when using autolayout for the subview, it does not get layoutet.Chamade
I created an example project showing the issue. Run on iOS 7 and 8 to see the difference. github.com/fabb/LabelTestChamade
I am also facing same issue. Did you get any answer on this?Autoeroticism
Seems issue has been fixed in iOS 8.1 beta version.Autoeroticism
G
5

I just want to add this answer because the question title may lead a lot of ppl here with similar issues (like me).

With iOS 8 to 8.0.2 LayoutSubviews calls are unreliable. They may not be called ever or (in my case) are called in a loop.

Even though you should not do it, it was pretty safe to alloc stuff in LayoutSubviews, but with this buggy (?!) behaviour it can cause hard-to-trace bugs.

I don't know if 8.1 fixes all the issues but it will be some time until customer devices will run 8.1 and they do run 8.0.2 NOW

Gunlock answered 2/10, 2014 at 14:37 Comment(3)
Am facing the same issue here. "LayoutSubviews" is called in a loop In order to cover users using iOS 8.0.2, Is there any Fix for this bug?Capitulation
no, to my knowledge there is no fix. But you should not try to support versions of iOS that were in-between-versions. If someone still uses 8.0 or 8.0.2 they can upgrade to a newer version and fix the problem themselves.Gunlock
Yeah that's true. But, unfortunately in apps, we can't ask every customer stucked on that version to upgrade their device. ;) Well, i think i have found a way around. Thanks for your reply. :)Capitulation
I
4

I had same issue. Really layoutSubviews is not called anymore for UILabel on iOS8, as Apple does not expect anybody uses it as superview.

I am using ReactiveCocoaLayout, so it can be done by subscribing to rcl_frameSignal or rcl_boundsSignal.

-(void)awakeFromNib { [ self.rcl_boundsSignal subscribeNext: ^( NSValue* boundsValue ) { //layout changed } ]; }

Or you can use simple KVO to know when frame has been changed:

-(void)dealloc
{
   [ self removeObserver: self forKeyPath: @"layer.bounds" ];
}

-(void)observeValueForKeyPath:( NSString* )keyPath
                     ofObject:( id )object
                       change:( NSDictionary* )change
                      context:( void* )context
{
   if ( [ keyPath isEqualToString: @"layer.bounds" ] )
   {
      //layoutSubviews
   }
   else
   {
      [ super observeValueForKeyPath: keyPath
                      ofObject: object
                        change: change
                       context: context ];
   }
}

-(void)awakeFromNib
{
   [ self addObserver: self
           forKeyPath: @"layer.bounds"
              options: NSKeyValueObservingOptionNew
              context: 0 ];
}
Idoux answered 10/9, 2014 at 12:44 Comment(1)
Note that UIKit is per documentation NOT KVO-compliant - even if it works for some cases, it might break in the future.Chamade
C
2

The bug was fixed by Apple in iOS 8.1 (beta).

Chamade answered 1/10, 2014 at 9:25 Comment(3)
do you have a link or something to back that up ?Gunlock
Can confirm, layoutSubview gets called again in 8.1 betaConnoisseur
I have filed a Radar with Apple. And I have created a sample project: github.com/fabb/LabelTestChamade

© 2022 - 2024 — McMap. All rights reserved.