I was successfully using SideMenu 2.3.4 in my app, then upgraded to v3.1.4. I made the few mods required to adjust to API changes, then ran my app - it crashed after the following UI actions:
Open the menu by tapping on the nav bar button
Tap on item that loads another view (the menu closes, the new view appears)
Tap on the nav bar button to open the menu again
The menu didn't open in response to that last tap before the app crashed. Under the debugger, I saw that after 2, viewDidLoad then viewWillAppear were called for that new view. After 3, viewWillDisappear, viewDidDisappear and viewWillAppear of that same view were called, all without any change in the display.
The crash happened in viewWillAppear because my code counts on viewDidLoad being the first thing that is called after viewDidDisappear. AFAIK, it is legitimate to count on that, since viewDidDisappear is supposed to mean that the view was closed and thus has to be reloaded and viewDidLoad called before any other life-cycle method can be called, i.e., viewWillAppear should not have been called before viewDidLoad.
Am I misunderstanding the iOS view life-cycle? Is this a bug in SideMenu 3.1.4?
Thanks,
Mark
A closer reading of the docs and articles on the net show that I did misunderstand the life-cycle methods.
There is no opposite of viewDidLoad (e.g., viewDidUnload), but in viewDidDisappear one can do this:
if (isBeingDismissed || isMovingFromParentViewController) {
// Do something - viewWillAppear will NOT be called before viewDidLoad.
}
That eliminates the crash I was seeing.
Mark
This question already has answers here:
iOS 7 - Difference between viewDidLoad and viewDidAppear
(7 answers)
Closed 6 years ago.
I am making iPhone app on swift,here ViewDidAppear and ViewWillAppear is being called multiple times on one viewDidLoad in ios swift app?
please help me.
Whenever You push a viewController, It will call viewDidLoad then viewWillAppear and last viewDidAppear.
But if you are coming back to viewController only viewWillAppear and viewDidAppear will call.
View will call these two (viewWillAppear & viewDidAppear) every time, whenever this viewController shows on every condition
i. On push - viewDidLoad after it, viewWillAppear & viewDidAppear.
ii. On back or pop - No viewDidLoad will call, Only viewWillAppear & viewDidAppear.
iii. On become active state - No viewDidLoad will call, Only viewWillAppear & viewDidAppear.
If you are not familiar with the UIViewController life cycle I really recommend you to start here Apple documentation and here.
But in a very short answer
The method viewDidLoad - This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.
The methods ViewDidAppear and ViewWillAppear as they sound to you, called every time the view Appear on the screen.
This image (from Apple documentation) shows the valid state transitions between various view ‘will’ and ‘did’ callback methods
I am using navigation controller. I have pushed two viewcontroller to navigation stack. When I am coming back to viewcontroller1 from viewcontroller2 using back button of navigation bar then viewdidload method of viewcontroller1 is called again.But as much as I know viewdidload is called only once at loading time. So why is this happening? Please tell me.
Thanks!!
-(void)viewDidLoad called only when view controller is loaded
but if you want to call any method then you can write code in
-(void)viewWillAppear
this method called every time when your view is appear.
About viewDidLoad
viewDidLoad: is called every time your view controller's view is loaded, not just the first time. The controller's view can be loaded and unloaded multiple times during the lifespan of the controller and viewDidLoad will be called every time. It may be unloaded whenever it's not on screen, usually if memory is low.
Best practices
Remember not to do view controller initialisation in viewDidLoad. This is a common mistake. For stuff that should only happen once when the view controller is loaded, do it in one of the controller's init methods.
If you're popping/dismissing back to it, viewDidLoad is not generally called, but viewDidAppear will.
The exception to this is in iOS versions prior to 6.0, if you received a memory warning, your view could be unloaded, and it will be reloaded when you pop back.
As you are pushing the viewcontrollers, AFAIK they create a new instance of the view controller they are presenting. When you get back to viewController1 it's viewDidLoad will not be called but the viewController2 viewDidLoad will be called every time you move from viewController1 to viewController2. When you perform pop from viewController2 it is deallocated there itself
I have a navigation based application and in the child view I have a button, tapping on which results in calling the popToRootViewController method.
-(IBAction)popToRootViewController
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
This should result in calling the viewWillAppear method of the rootViewController and it is happening in most of the cases. However, occasionally viewDidLoad of rootViewController is called. I am not able to find the reason behind it. Does any one has any idea why viewDidLoad is called sometimes?
On iOS 5 and Earlier, the System May Unload Views When Memory Is Low:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html
viewDidLoad is called once when view controller's view is loaded first time.
viewWillAppear will be called after viewDidLoad method when view controller's view is loaded first time.
Now when ever u push or pop controller in navigationController, the visible controller's viewWillApper method will be called surely.
viewDidLoad, as the name implies, is called just after a view controller has loaded its view. If a view controller is no longer the frontmost controller, it may release its view to save memory (and it used to call viewWillUnload and viewDidUnload which are now deprecated in iOS 6). If this happens, when it comes to front again (or whenever something calls thecontroller.view), it will recreate the view (if is not Nib-based, it will call loadView), and then call viewDidLoad.
Could you explain me the correct manner to manage the UIViewController lifecycle?
In particular, I would like to know how to use Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnload and Dispose methods in Mono Touch for a UIViewController class.
All these commands are called automatically at the appropriate times by iOS when you load/present/hide the view controller. It's important to note that these methods are attached to UIViewController and not to UIViews themselves. You won't get any of these features just using a UIView.
There's great documentation on Apple's site here. Putting in simply though:
ViewDidLoad - Called when you create the class and load from xib. Great for initial setup and one-time-only work.
ViewWillAppear - Called right before your view appears, good for hiding/showing fields or any operations that you want to happen every time before the view is visible. Because you might be going back and forth between views, this will be called every time your view is about to appear on the screen.
ViewDidAppear - Called after the view appears - great place to start an animations or the loading of external data from an API.
ViewWillDisappear/DidDisappear - Same idea as ViewWillAppear/ViewDidAppear.
ViewDidUnload/ViewDidDispose - In Objective-C, this is where you do your clean-up and release of stuff, but this is handled automatically so not much you really need to do here.
UPDATE: ViewDidUnload was deprecated in iOS 6, so updated the answer accordingly.
The UIViewController lifecycle is diagrammed here:
The advantage of using Xamarin Native/Mono Touch, is that it uses the native APIs, and so it follows the same ViewController lifecycle as you would find in Apple's Documentation.
This is for latest iOS Versions(Modified with Xcode 9.3, Swift 4.1). Below are all the stages which makes the lifecycle of a UIViewController complete.
loadView()
loadViewIfNeeded()
viewDidLoad()
viewWillAppear(_ animated: Bool)
viewWillLayoutSubviews()
viewDidLayoutSubviews()
viewDidAppear(_ animated: Bool)
viewWillDisappear(_ animated: Bool)
viewDidDisappear(_ animated: Bool)
Let me explain all those stages.
1. loadView
This event creates/loads the view that the controller manages. It can load from an associated nib file or an empty UIView if null was found.
This makes it a good place to create your views in code programmatically.
This is where subclasses should create their custom view hierarchy if they aren't using a nib.
Should never be called directly.
Only override this method when you programmatically create views and assign the root view to the view property
Don't call super method when you override
loadView
2. loadViewIfNeeded
If incase the view of current viewController has not been set yet then this method will load the view but remember, this is only available in iOS >=9.0. So if you are supporting iOS <9.0 then don't expect it to come into the picture.
Loads the view controller's view if it has not already been set.
3. viewDidLoad
The viewDidLoad event is only called when the view is created and loaded into memory but the bounds for the view are not defined yet. This is a good place to initialise the objects that the view controller is going to use.
Called after the view has been loaded. For view controllers created in code, this is after -loadView.
For view controllers unarchived from a nib, this is after the view is set.
4. viewWillAppear
This event notifies the viewController whenever the view appears on the screen. In this step the view has bounds that are defined but the orientation is not set.
Called when the view is about to made visible. Default does nothing.
5. viewWillLayoutSubviews
This is the first step in the lifecycle where the bounds are finalised. If you are not using constraints or Auto Layout you probably want to update the subviews here. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.
Called just before the view controller's view's layoutSubviews method is invoked.
Subclasses can implement as necessary. The default is a nop.
6. viewDidLayoutSubviews
This event notifies the view controller that the subviews have been setup. It is a good place to make any changes to the subviews after they have been set. This is only available in iOS >=5.0. So if you are supporting iOS <5.0 then don't expect it to come into the picture.
Called just after the view controller's view's layoutSubviews method is invoked.
Subclasses can implement as necessary. The default is a nop.
7. viewDidAppear
The viewDidAppear event fires after the view is presented on the screen. Which makes it a good place to get data from a backend service or database.
Called when the view has been fully transitioned onto the screen.
Default does nothing
8. viewWillDisappear
The viewWillDisappear event fires when the view of presented viewController is about to disappear, dismiss, cover or hide behind other viewController. This is a good place where you can restrict your network calls, invalidate timer or release objects which is bound to that viewController.
Called when the view is dismissed, covered or otherwise hidden.
9. viewDidDisappear
This is the last step of the lifecycle that anyone can address as this event fires just after the view of presented viewController has been disappeared, dismissed, covered or hidden.
Called after the view was dismissed, covered or otherwise hidden.
Default does nothing
Now as per Apple when you are implementing this methods you should remember to call super implementation of that specific method.
If you subclass UIViewController, you must call the super implementation of this method, even if you aren't using a NIB. (As a convenience, the default init method will do this for you, and specify nil for both of this methods arguments.) In the specified NIB, the File's Owner proxy should have its class set to your view controller subclass, with the view outlet connected to the main view. If you invoke this method with a nil nib name, then this class' -loadView method will attempt to load a NIB whose name is the same as your view controller's class. If no such NIB in fact exists then you must either call -setView: before -view is invoked, or override the -loadView method to set up your views programatically.
Hope this helped.
Thanks.
UPDATE - As #ThomasW pointed inside comment viewWillLayoutSubviews and viewDidLayoutSubviews will also be called at other times when subviews of the main view are loaded, for example when cells of a table view or collection view are loaded.
UPDATE - As #Maria pointed inside comment, description of loadView was updated
iOS 10,11 (Swift 3.1,Swift 4.0)
According to UIViewController in UIKit developers,
1. loadView()
This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.
2. loadViewIfNeeded()
Loads the view controller's view if it has not already been set.
3. viewDidLoad()
Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.
4. viewWillAppear(_ animated: Bool)
Called when the view is about to made visible. Default does nothing
5. viewWillLayoutSubviews()
Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.
6. viewDidLayoutSubviews()
Called just after the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. Default does nothing.
7. viewDidAppear(_ animated: Bool)
Called when the view has been fully transitioned onto the screen. Default does nothing
8. viewWillDisappear(_ animated: Bool)
Called when the view is dismissed, covered or otherwise hidden. Default does nothing
9. viewDidDisappear(_ animated: Bool)
Called after the view was dismissed, covered or otherwise hidden. Default does nothing
10. viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
Called when the view is Transitioning.
11. willMove(toParentViewController parent: UIViewController?)
12. didMove(toParentViewController parent: UIViewController?)
These two methods are public for container subclasses to call when transitioning between child controllers. If they are overridden, the overrides should ensure to call the super.
The parent argument in both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new parent view controller.
13. didReceiveMemoryWarning()
Called when the parent application receives a memory warning. On iOS 6.0 it will no longer clear the view by default.
As of iOS 6 and onward. The new diagram is as follows:
Let's concentrate on methods, which are responsible for the UIViewController's lifecycle:
Creation:
- (void)init
- (void)initWithNibName:
View creation:
- (BOOL)isViewLoaded
- (void)loadView
- (void)viewDidLoad
- (UIView *)initWithFrame:(CGRect)frame
- (UIView *)initWithCoder:(NSCoder *)coder
Handling of view state changing:
- (void)viewDidLoad
- (void)viewWillAppear:(BOOL)animated
- (void)viewDidAppear:(BOOL)animated
- (void)viewWillDisappear:(BOOL)animated
- (void)viewDidDisappear:(BOOL)animated
- (void)viewDidUnload
Memory warning handling:
- (void)didReceiveMemoryWarning
Deallocation
- (void)viewDidUnload
- (void)dealloc
For more information please take a look on UIViewController Class Reference.
The methods viewWillLayoutSubviews and viewDidLayoutSubviews aren't mentioned in the diagrams, but these are called between viewWillAppear and viewDidAppear. They can be called multiple times.
Haider's answer is correct for pre-iOS 6. However, as of iOS 6 viewDidUnload and viewWillUnload are never called. The docs state: "Views are no longer purged under low-memory conditions and so this method is never called."
There's a lot of outdated and incomplete information here. For iOS 6 and newer only:
loadView[a]
viewDidLoad[a]
viewWillAppear
viewWillLayoutSubviews is the first time bounds are finalized
viewDidLayoutSubviews
viewDidAppear
* viewWillLayoutSubviews[b]
* viewDidLayoutSubviews[b]
Footnotes:
(a) - If you manually nil out your view during didReceiveMemoryWarning, loadView and viewDidLoad will be called again. That is, by default loadView and viewDidLoad only gets called once per view controller instance.
(b) May be called an additional 0 or more times.
Explaining State Transitions in the official doc: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html
This image shows the valid state transitions between various view ‘will’ and ‘did’ callback methods
Valid State Transitions:
Taken from: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png
As per Apple's doc — Start Developing iOS Apps (Swift)
— Work with View Controllers — Understand the View Controller Lifecycle
viewDidLoad()—Called when the view controller’s content view (the top of its view hierarchy) is created and loaded from a storyboard.
…
Use this method to perform any additional setup required by your view controller.
viewWillAppear()—Called just before the view controller’s content view is added to the app’s view hierarchy. Use this method to trigger any operations that need to occur before the content view is presented onscreen
viewDidAppear()—Called just after the view controller’s content view has been added to the app’s view hierarchy. Use this method to trigger any operations that need to occur as soon as the view is presented onscreen, such as fetching data or showing an animation.
viewWillDisappear()—Called just before the view controller’s content view is removed from the app’s view hierarchy. Use this method to perform cleanup tasks like committing changes or resigning the first responder status.
viewDidDisappear()—Called just after the view controller’s content view has been removed from the app’s view hierarchy. Use this method to perform additional teardown activities.