2

An app I had working on iOS 7 and 8 has had some minor issues on iOS9, one of which being that a single view controller gets the wrong height.

The following code:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self layoutViews];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [self layoutViews];
}

- (void)layoutViews {
    NSLog(@"Size-> %@", NSStringFromCGRect(self.view.frame));
}

Produces the following erroneous output:

2015-11-06 22:42:31.737 app[62442:1136052] Size-> {{0, 0}, {375, 667}}
2015-11-06 22:42:33.318 app[62442:1136052] Size-> {{0, 32}, {667, 343}}
2015-11-06 22:42:34.885 app[62442:1136052] Size-> {{0, 64}, {375, 603}}
2015-11-06 22:45:18.063 app[62442:1136052] Size-> {{0, 32}, {667, 343}}

When I:

  1. Open the VC in portrait
  2. Rotate to landscape
  3. Rotate back to portrait
  4. Rotate back to landscape

It seems that the initial load of the VC provides the wrong size under self.frame.size, while all subsequent rotations are correct. The height of 603 is correct, but you can see that upon the two rotations to landscape that it's still incorrect at 667.

I thought that something to do with the nav controller bar could be breaking it. My code in the viewDidLoad method is simply:

- (void)viewDidLoad {
    if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
        [self setEdgesForExtendedLayout:UIRectEdgeNone];
    }

    [super viewDidLoad];
}

Which works fine on iOS 8.

Update Fixed this by adding the call to viewDidAppear:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self layoutViews];
    [activitiesTable flashScrollIndicators];
}
Perry Mitchell
  • 665
  • 6
  • 16

2 Answers2

0

I am not sure why you are adding setEdgesForExtendedLayout in viewDidLoad .I tried your way

with UIRectEdgeNone:

2015-11-06 19:40:41.881 Test[934:275179] Size-> {{0, 64}, {375, 603}}

I have the navigation bar on my view controller.

with UIRectEdgeTop && UIRectEdgeAll:

2015-11-06 19:52:18.086 Test[1113:331687] Size-> {{0, 0}, {375, 667}}

with UIRectEdgeLeft && UIRectEdgeBottom && UIrectEdgeRight && UIRectEdgeNone:

2015-11-06 19:54:43.864 Test[1137:343893] Size-> {{0, 64}, {375, 603}}

As stated in the documentation:

In iOS 7, view controllers use full-screen layout. At the same time, iOS 7 gives you more granular control over the way a view controller lays out its views. In particular, the concept of full-screen layout has been refined to let a view controller specify the layout of each edge of its view.

The wantsFullScreenLayout view controller property is deprecated in iOS 7. If you currently specify wantsFullScreenLayout = NO, the view controller may display its content at an unexpected screen location when it runs in iOS 7.

Use edgesForExtendedLayout to specify which edges of a view should be extended, regardless of bar translucency. By default, the value of this property is UIRectEdgeAll.

If you look into the view Debugger under the cases UIRectEdgeAll vs UIRectEdgeNone

If you use UIRectEdgeAll, the view controller view use full screen layout: enter image description here

If you use UIRectEdgeNone, the view controller will not use the full screen layout,it will push the view right towards the bottom of the navigation bar:

enter image description here

I suggest to use UIEdgeRectAll instead of UIEdgeRectNone unless you really want to organize the frames of the all subviews including your view controller view!!!!

Teja Nandamuri
  • 11,045
  • 6
  • 57
  • 109
  • There's nothing wrong with using UIEdgeRectNone. The default value is UIRectEdgeAll because the default behavior is a translucent navigation bar with content showing underneath. When using an opaque navigation bar, it makes sense to show content just below it. – Mercurial Nov 07 '15 at 09:41
  • I use UIRectEdgeNone to get around the annoyances that come with views moving under the nav bar - so far this has been the simplest way I've found programmatically. What is confusing is why my example *changes* height after rotating. I don't mind so much how it behaves, so long as it's consistent. With your example of UIRectEdgeLeft + UIRectEdgeRight + UIRectEdgeBottom + UIRectEdgeNone, I get 667 tall, 667 long (rotated), 603 tall (rotated), which is the same as what I was getting before. The height is inconsistent no matter what I set there.. – Perry Mitchell Nov 07 '15 at 13:10
  • I see, sorry for the confusion. Unfortunately the issue wasn't with edgesForExtendedLayout, but with the viewDidAppear that @maulik-patel suggested. Thanks for the detailed answer! – Perry Mitchell Nov 08 '15 at 07:26
0

Your code is correct and its work perfect after first time load.

So issue With First load application.

Apple Document for Auto layout provide the answer.

You just need to write your code in viewDidAppear: method.

So write your code from viewDidLoad: method to

-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated]; }
Nilesh
  • 701
  • 5
  • 14
Maulik Patel
  • 397
  • 4
  • 15
  • I even tried this. I called the setEdgesForExtendedLayout in did load and did appear, it gave me the same result!!!! – Teja Nandamuri Nov 07 '15 at 13:22
  • This worked, I'd neglected the `viewDidAppear` method. It was necessary, in iOS9, to additionally fire the `layoutViews` custom method in `viewDidAppear`. This shows a distinct difference in behaviour in iOS9, but hey.. we're used to that ;) – Perry Mitchell Nov 08 '15 at 07:28