I was wondering if anyone knows why when you set the frame of a subview in viewDidLoad
and viewWillAppear
the changes do not take affect on the screen, but if you set it in viewDidAppear
they do?
In my case I am loading a custom xib with two tableviews then attempting to shift them down in viewDidLoad
to allow space for another view which is added in viewDidLoad
as it is not always necessary to display it.
The problem is when i set frame in viewDidLoad
or viewWillAppear
it is set on the object, i can see by printing it out, but it is not reflected on screen. Moving my set frame calls to viewDidAppear
will cause everything to work as expected.
Is it wrong to think I should be able to set the frame in viewDidLoad
?
- (id)init { if ( self = [super initWithNibName:@"MyView" bundle:nil] ) {} return self; } - (void)viewDidLoad { [super viewDidLoad]; self.descriptionWebView = [[[UIWebView alloc] initWithFrame:CGRectMake( 0, 0, self.view.frame.size.width, 200 )] autorelease]; [self.view addSubview:self.descriptionWebView]; self.tableView1.autoresizingMask = UIViewAutoresizingNone; self.tableView2.autoresizingMask = UIViewAutoresizingNone; [self.descriptionWebView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"...." withExtension:@"html"]]]; table1LocationWithHeader = CGRectMake( self.tableView1.frame.origin.x, 200, self.tableView1.frame.size.width, self.tableView1.frame.size.height - 200 ); table2LocationWithHeader = CGRectMake( self.tableView2.frame.origin.x, 200, self.tableView2.frame.size.width, self.tableView2.frame.size.height - 200 ); //this will NOT work self.tableView1.frame = table1LocationWithHeader; self.tableView2.frame = table2LocationWithHeader; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //this will NOT work self.tableView1.frame = table1LocationWithHeader; self.tableView2.frame = table2LocationWithHeader; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; //this WILL work self.tableView1.frame = table1LocationWithHeader; self.tableView2.frame = table2LocationWithHeader; } //I added these after comments for stack overflow users, it seems like viewDidLayoutSubviews is the best place to set the frame - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; //this will NOT work self.tableView1.frame = table1LocationWithHeader; self.tableView2.frame = table2LocationWithHeader; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; //this WILL work self.tableView1.frame = table1LocationWithHeader; self.tableView2.frame = table2LocationWithHeader; }
There is a noticeable pause after row selection and before the new view is pushed. Some logging indicates that all of my code is reasonably quick, from row selection until the pushed controller's viewWillAppear . But then the time between viewWillAppear and viewDidAppear is logged at around 0.7 seconds.
viewDidLoad is called once when the controller is created and viewDidAppear is called each time the view, well, DID appear. So say you have a modal view that you present, when that view is dismissed, viewDidAppear will be called, and viewDidLoad will not be called.
viewDidAppear is called once you see the loaded view on screen. It is called after view appeared. ViewDidAppear is called everytime when you see the view after it is loaded. if you push and then pop any other viewController on that view then again viewDidAppear gets called.
The difference between viewDidAppear and viewDidLoad is that viewDidAppear is called every time you land on the screen while viewDidLoad is only called once which is when the app loads.
viewDidLoad is called when the class is loaded however no ui elements have been initialised and therefore any attempt to reference them will be overwritten or unavaliable during the initialisation process which happens between the viewDidLoad and viewDidAppear calls. Once all ui element have been initalised and drawn viewDidAppear is called.
viewDidLoad - Called after the controller's view is loaded into memory
At this point the view isn't within the view hierarchy.
viewWillAppear - Notifies the view controller that its view is about to be added to a view hierarchy.
Again, the view is yet to be added to the view hierarchy.
viewDidAppear - Notifies the view controller that its view was added to a view hierarchy.
Only then is the view added to the view hierarchy.
Update
The viewDidLayoutSubviews
is the most appropriate place to modify the UI before it actually appears on the screen.
viewDidLayoutSubviews - Notifies the view controller that its view just laid out its subviews.
See this thread When is layoutSubviews called?
When use autolayout, framework do not call layoutSubviews automatically. That is very important. From ref:
If you add subview in viewDidLoad, layoutSubviews called before viewDidAppear, and you can get the correct size of subviews. But if you do nothing, layoutSubviews will be called after viewDidAppear. It's up to your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With