Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 9 changed view load behaviour

I have noticed a change in how iOS 9 loads/displays views compared to previous versions of iOS. Here's an output of self.view.frame in iOS 8.4

viewDidLoad {{0, 0}, {320, 504}}
viewWillAppear {{0, 64}, {320, 504}}
viewDidAppear {{0, 64}, {320, 504}}

And here's the same for iOS 9

viewDidLoad {{0, 0}, {320, 504}}
viewWillAppear {{0, 0}, {320, 504}}
viewDidAppear {{0, 64}, {320, 504}}

Notice that in viewWillAppear method iOS 9 fails to update the origin of self.view.frame.

This causes certain issues in my app such as views initially being position incorrectly.

Does anyone know if it's intended or it's a defect? And perhaps a quick fix?

like image 976
artooras Avatar asked Sep 24 '15 16:09

artooras


1 Answers

I found the same change in iOS 9 versus previous iOS versions: in viewWillAppear, self.view.frame and self.view.bounds only show the default size used in the nib instead of the size actually used at runtime. This means if, for example, your nib has a default width of 320 but you run it on an iPhone 6, the width will be incorrectly reported as 320 instead of 375.

You could use [[UIScreen mainScreen] bounds], as suggested in the comments to the question, but that would only work if your views always fill the screen. If you have a split-screen design on an iPad and you need to know the actual display width of an individual view, it is not available in viewWillAppear.

You could use viewWillLayoutSubviews instead of viewWillAppear, because the frame and bounds are correctly set at that point. However, this is not called every time a view appears, only when it first appears, so your app behavior will change slightly.

I'm using a combination of viewWillAppear and viewWillLayoutSubviews, along with a new instance variable, to replicate the pre-iOS 9 behavior in iOS 9:

@synthesize sizingReady;

- (void)viewDidLoad {
    [super viewDidLoad];

    // set a flag telling us whether the view size is available
    // this is needed in iOS 9 because the view size isn't updated in viewWillAppear yet
    self.sizingReady = FALSE;
}

- (void)viewWillAppear:(BOOL)animated {
    // don't do anything until the view size is available, which doesn't happen until viewWillLayoutSubviews in iOS 9
    if (!self.sizingReady) {
        return;
    }

    [super viewWillAppear:animated];

    // your code goes here
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    if (!self.sizingReady) {
        self.sizingReady = TRUE;
        [self viewWillAppear:TRUE];
    }
}
like image 58
arlomedia Avatar answered Oct 09 '22 14:10

arlomedia