16

I'm trying to solve a view placement bug that has arisen as of iOS 9. I am instantiating a view controller from a xib file (non-autolayout) and then pushing this onto my UINavigationController.

The problem is that when the view controller's viewWillAppear method is called, its frame has not yet been adjusted to the navigation controller's size and is still what was set in the xib file. It doesn't get set properly now until viewDidAppear.

This is completely screwing up my code. Does anyone know precisely what has changed that is causing this and what is the best way to handle it? I don't want to wait until viewDidAppear because this will look bad and make for a poor user experience.

devios1
  • 33,997
  • 43
  • 149
  • 241
  • 1
    I am encountering the same issue. Upon further inspection it looks like the child view hasn't even been added to the UINavigationController's view yet (view.superview == nil) – Brody Robertson Sep 29 '15 at 19:25

4 Answers4

11

I am also looking for the best fix.

My temporary one is to call the code that was in "viewDidAppear" in "viewDidLayoutSubviews". That way, my code will get called as soon as the frames are set.

But, make sure to add a boolean or something so that your code doesn't get called every time viewDidLayoutSubviews is called

-(void)viewDidLayoutSubviews{
   if (didLayoutSubviews == NO){
       didLayoutSubviews = YES;
       // perform code that was in viewWillAppear
   }
}
NickProvost
  • 357
  • 5
  • 20
  • Thanks Nick, this did the trick! Unfortunate that this is necessary. `viewWillAppear` was the perfect conceptual place to put this code previously. Now it feels like we have to do a hack to do what came naturally before. :( – devios1 Sep 21 '15 at 17:26
0

I occurred this issue too,

try to uncheck option "Resize View From NIB" from storyboard

PatrickSCLin
  • 1,307
  • 1
  • 14
  • 43
0

Try moving the layout code from viewWillAppear to viewWillLayoutSubviews.

Ken
  • 597
  • 4
  • 8
  • 29
0

A little bit updated NickProvost's answer:

private var loadViewToken: dispatch_once_t = 0

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    dispatch_once(&loadViewToken) { [weak self] in
        if let wSelf = self {
            wSelf.setupView()
        }
    }
}
edzio27
  • 4,048
  • 6
  • 29
  • 48