4

I've been searching but can't find an answer to this issue I'm having. It seems fairly fundamental, so hopefully someone can explain, or point me towards a previous post.

When adding a viewcontroller's view as a subview of another viewcontroller, I find that the subview's height property goes to zero upon rotation. The width tends to increase as well.

For example, with NSDChildViewController's view set to 50x100 in the xib file...

@implementation ParentViewController

-(void)viewDidLoad
{
  [super viewDidLoad];
  mChild = [[ChildViewController alloc] initWithNibName:nil
                                                  bundle:nil];
  [self.view addSubview:mChild.view];
}

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [mChild printFrame];
}
@end

@implementation ChildViewController

-(void)printFrame
{
    NSLog(@"%s %@",__FUNCTION__, NSStringFromCGRect(self.view.frame));
}
@end

The logging for respective orientations portrait->landscape->portrait is as follows:

-[ChildViewController printFrame] {{0, 0}, {50, 100}}

-[ChildViewController printFrame] {{0, 0}, {298, 0}}

-[ChildViewController printFrame] {{0, 0}, {50, 248}}

Why does this happen and how can I prevent it? Presently it's causing me trouble whilst trying to programmatically layout viewcontrollers as subviews. The only solution I've found so far is to force the size property back to 50x100 using something like this...

-(void)forceSize
{
    CGRect frame = self.view.frame;
    frame.size.width=50;
    frame.size.height=100;
    self.view.frame=frame;
}

but the above seems ludicrous. Any help appreciated.

Scaroth
  • 187
  • 1
  • 11

1 Answers1

3

Your parent view is automatically resizing its child views when its frame changes. In this case, the parent view's frame is changing when the device switches between portrait and landscape mode.

You appear to be testing on a 4-inch iPhone device (or simulator), so the dimensions we're playing with are: 320 x 568. The parent view uses up the full width and height of the screen.

Here's what's happening:

Before rotation from portrait to landscape:

widthDifference = parentViewWidth - originalChildViewWidth      // 270 (320 - 50)
heightDifference = parentViewHeight - originalChildViewHeight   // 468 (568 - 100)

After rotation from portrait to landscape:

childLandscapeViewWidth = parentViewHeight - widthDifference    // 298 (568 - 270)
childLandscapeViewHeight = parentViewWidth - heightDifference   // -148 (320 - 468)
    // (but height cannot be < 0, so this is automatically set to 0)

So in landscape mode we end up with the child view's width = 298 and height = 0

Before rotation from landscape to portrait:

widthDifference = parentViewWidth - childLandscapeViewWidth     // 270 (568 - 298)
heightDifference = parentViewHeight - childLandscapeViewHeight  // 320 (320 - 0)

After rotation from landscape to portrait:

childPortraitViewWidth = parentViewWidth - widthDifference      // 50 (320 - 270)
childPortraitViewHeight = parentViewHeight - heightDifference   // 248 (568 - 320)

And ultimately we end up with the child view's width = 50 and height = 248

So, to put a stop to this craziness set autoresizesSubviews on the parent view (which is YES by default) to NO like so:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.autoresizesSubviews = NO;
    ...
}
gavdotnet
  • 2,214
  • 1
  • 20
  • 30
  • That's it! Thanks for taking the time to write a clear solution. I'll up-vote your response once I have sufficient reputation ;) – Scaroth Sep 08 '14 at 21:43
  • No problem. In the meantime could you please accept it as the correct answer? – gavdotnet Sep 08 '14 at 21:52