layoutSubviews recursive called in iOS 13.2 beta1

The same code works well from iOS 9.0 to iOS 13.1.2, but stuck in iOS 13.2 beta1.

When layout subviews called, it goes recursive and cpu goes to 100%.


Step to reproduce:

1. Subclass a UITextView

2. Set some text

3. Set font or textColor in layoutSubviews method

4. Add this view to the screen


Here's the code:

#import <UIKit/UIKit.h>

@interface TYTextView : UITextView

@end


@implementation TYTextView

- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.text = @"Some text";
}
return self;
}

- (void)layoutSubviews {
[super layoutSubviews];


self.font = [UIFont systemFontOfSize:13];
self.textColor = [UIColor redColor];
}

@end

I would suspect that if you comment out the setfont, problem disappear.


Excat ?


If so, have you set constraints on the TYTextView ?

I have set constraints on the TYTextView and if I comment out the setfont then problem disappear. Is autolayout will cause this system bug?

Accepted Answer

I cannot be totally sure, but I anlyze situation as follows.


- You have constraints

- So, if OS thinks that something may change layout through those constraints, it calls systemLayout (even when nothing changes in fact, but that is what the layout engine has to check by recomputing)

- In layoutSubviews, you set the font size on an object which has constraints. That triggers a call to recompute layout, hence the infinite loop on layoutSubviews

- probably the same would occur if you set the font style to bold or normal.


That is a logical behavior, not a bug, and probably something that was improved in IOS 13.


As conclusion: don't call API that MAY change object size in layoutSubviews.

Why dont you call

self.font = [UIFont systemFontOfSize:13];


in an init or viewWillLoad for instance.


Have a look here as well :

https://stackoverflow.com/questions/40520851/how-to-avoid-infinite-layoutsubviews

with the advice :

layoutSubviews
should only ever do one thing - adjust the bounds/frames of a view's subviews. That's it. No other changes of any kind should be done there.

Thanks very much for answer

From the SO thread, seems this behavior is not new to IOS13.


Don't forget to close the thread.

Nope, this behavior has changed from iOS 13.2 beta.

We have at least 10k+ users and every version we published before fully test. this behavior change made our app stuck at first screen, it's very easy to reproduce.

iOS 13.0 - 13.1.2 works well, I'm sure.

layoutSubviews recursive called in iOS 13.2 beta1
 
 
Q