I have discovered a strange behavior in my application, where a connected IBOutlet
has its connected view's frame between the calls in my view controller to viewWillAppear:
and viewDidAppear:
. Here is the relevant code in my UIViewController
subclass:
-(void)viewWillAppear:(BOOL)animated { NSLog(@"%@", self.scrollView); } -(void)viewDidAppear:(BOOL)animated { NSLog(@"%@", self.scrollView); }
and the resulting log output:
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 0; 0 0); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}> MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 44; 320 416); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
Which clearly shows that the frame is changing between the two calls. I wanted to do setup with the view in the viewDidLoad
method, but if the content is not available for me to change until it is on the screen, that seems pretty useless. What could be happening?
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: Whatever processing you have that needs to be done once. viewWilLAppear: Whatever processing that needs to change every time the page is loaded. Labels, icons, button titles or most dataInputedByDeveloper usually don't change.
viewWillAppear(_:)Always called after viewDidLoad (for obvious reasons, if you think about it), and just before the view appears on the screen to the user, viewWillAppear is called.
The methods ViewDidAppear and ViewWillAppear as they sound to you, called every time the view Appear on the screen. thanks for helping me.
From the documentation:
viewWillAppear:
Notifies the view controller that its view is about to be added to a view hierarchy.
viewDidAppear:
Notifies the view controller that its view was added to a view hierarchy.
As a result the frames of the subviews aren't yet set in the viewWillAppear
:
The appropriate method to modify your UI before the view is presented to the screen is:
viewDidLayoutSubviews
Notifies the view controller that its view just laid out its subviews.
Autolayout
made a huge change in how we design and develop the GUI of our views. One of the main differences is that autolayout
doesn't change our view sizes immediately, but only when is triggered, that means at a specific time, but we can force it to recalculate our constraints immediately or mark them as "in need" of layout. It works like -setNeedDisplay
.
The big challenge for me was to understand and accept that, we do not need to use autoresizing masks anymore, and frame has become a useless property in placing our views. We do not need to think about view position anymore, but we should think how we want to see them in a space related to each other.
When we want to mix old autoresizing mask and autolayout is when problems arise. We should think about autolayout implementation really soon and try to avoid to mix the old approach in a view hierarchy based on autolayout.
Is fine to have a container view that uses only autoresizing masks, such as a main view of a view controller, but is better if we do not try to mix.
I never used storyboard, but most proably it is correct. Using Autolayout, frame of your views are set when the autolayout engine starts its calculation. Try to ask the same thing right after super of - (void)viewDidLayoutSubviews
method of your view controller.
This method is called when the autolayout engine has finished to calculate your views' frames.
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