Everybody knows that you can't trust the frame size on a UIViewController init/viewDidLoad method; this:
- (void)viewDidLoad: {
NSLog(@"%d", self.view.frame.size.width);
}
will print wrong sizes in many occasions (in particular it's pretty much broken in landscape mode)
This will actually return always corrected results so it's good to layout the subviews:
- (void)viewWillAppear: {
NSLog(@"%d", self.view.frame.size.width);
}
The problem is that viewWillAppears gets called every time the view appears, so it's not suitable to alloc or add subviews. So you end up declaring every single view in the interface and you end up with huge header files that I don't like at all since most of the items don't need any more manipulations after the initial setup.
So question one is: Is there a better way to handle subviews positioning?
Question two is very related, let's say I have a subclass of UIView including various others subviews. I declare it inside my interface, and i alloc/init it in my init/viewDidLoad method.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
...
menu = [[SNKSlidingMenu alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
...
}
As we already know we now need to reposition it in viewWillAppear to get a more accurate reading
- (void)viewWillAppear:(BOOL)animated{
....
menu.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
....
}
The problem is that of course all the subviews needs to be repositioned as well. This is done by the layoutSubviews function that get called automatically, but we got the same problem: All the subviews need to be declared inside the interface of the SNKSlidingMenu class.. Is there a way around this?
Thanks.
viewWillLayoutSubviews
andviewDidLayoutSubviews
can resolve this problem.But the two methed would be performed more times. this is my code to get correct
self.view.frame
.If you are targetting iOS 5.0 or better you can use
viewWillLayoutSubviews
andviewDidLayoutSubviews
to make changes.As for your second question, if you need access to an instance variable in other method than
init
, you need to keep it around, I don't see a problem with it.You can, however, try to use Auto Layouts and set up rules between the subviews so it's automatically laid out for you without the need to keep a reference.
viewDidLoad
only gets called when your view is created, but lots of things can affect theframe
's size, and it doesn't get called again whenframe
changes.Instead:
viewDidLoad
viewWillLayoutSubviews
.See some additional discussion here for handling rotation: https://stackoverflow.com/a/16421170/1445366