When are views and view controllers initialized/instantiated in iOS? [closed] - ios

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am new to iOS programming. I wonder when all the views and view controllers will be created.
At the time when the app launched all views and their controllers are created
or
when the view become active (displayed on the screen), it and its controller will be created(also, when it becomes inactive, it will be deallocated)?
Thanks!

The answer is neither really, but it depends on the structure of your app. The views are not created until you reference them, or the view is about to be put on screen. The controllers though can be instantiated at different times, that could be well before the view is created. For instance, when using a tab bar controller, all of the controllers are instantiated right after the tab bar controller itself, but only the view of the tab at index 0 is created and displayed. The other views are not loaded until you click on one of the other tabs. With segues, the controllers are created when the segue is called, and the views are loaded shortly thereafter (but after prepareForSegue is called in the calling class which is why you can't reference any of the destination controller's views in that method).
The view controllers and their views will be deallocated when there is no longer any strong pointer to them. Again, when that happens depends on how your app is set up. For instance, with a navigation controller, when you push to another controller, the initial one is not on screen any more, but the navigation controller has a strong reference to it, so it is not deallocated. However, when you pop a view controller (off the navigation controller's stack), it will be deallocated, unless you keep a pointer to it yourself.

I believe something happens in main() that initializes the app delegate when your app first starts. The app delegate initializes the window object which manages displaying content to your screen. The app delegate's application:didFinishLaunchingWithOptions is the entry point into our app's logic. Here is where you can initialize and set your root view controller although it's taken care of for you, especially if you're using storyboard.
After the root view controller is initialized it'll go through a series of steps setting up it's views.
viewDidLoad()
viewWillAppear()
viewDidAppear()
viewWillLayoutSubviews
are some events you can respond to as it's being set up. I assume somewhere between viewDidAppear and viewWillLayoutSubviews is when similar events are called for that view controller's subviews.
viewWillDisappear()
viewDidDisappear()
viewDidUnLoad()
are the other events of interest.

If you are using StoryBoards, the root view controller defined in it is the view that will be loaded at app launch after that, you control the flow of the application yourself with a navigation controller for example.
For controlling the life cycle of your views, your controllers and the app, the OS will send messages to your classes that represent events. These can be events of the app launching, the view appearing on the screen or a class being instantiated.
Here are a few examples:
When your app first launches, the OS will call application:didFinishLaunchingWithOptions: in your app delegate.
When a viewControlles's View is about to appear on the screen, the OS will call viewWillAppear() on the viewController.
When you create a view from the storyBoard, the method initWithCoder: get called on the view's class.
Here are some docs that explain it better: UIApplicationDelegate Protocol and View Controller Programming Guide: Resource Management.

Related

self.navigationController is nil during state restoration

After implementing state restoration in my app I am having difficulty with my view controllers.
My issue is that in viewDidLoad of the view controller I am attempting to restore the self.naigationController property, which is nil.
I have set breakpoints in the viewDidLoad method of each view controller that comes before the one I am trying to restore. In the first view controller, the navigation controller is found. In every one after that, including the one I am trying to restore, the navigation controller is nil.
This is causing bugs where I cannot set the navigation bar visibility, views are misplaced, etc.
Does anyone have an idea why this might be?
Try moving the code to viewWillAppear.
Unlike viewDidLoad, viewWillAppear can get called multiple times, so take care to make sure your code is idempotent. That is, make sure the results are what you expect if the method is called repeatedly. For example, make sure you don't initialize a new subview if the view has already been added.
The navigationController property searches up the parentViewControllers to find one of class UINavigationController. Only view controllers loaded from the storyboard can find their navigation controller at the viewDidLoad time (and in awakeFromNib). It is likely you are instantiating a new instance of the view controller during the restore process rather than using the one that was created by the storyboard. The solution is either to help the restore process find the existing view controller if it has changed paths e.g. because of split controller orientation change (via viewControllerForRestorationPathComponents in your app delegate) although that comes with its own set of issues, or make your view controller work by not requiring the nav controller in the viewDidLoad, e.g. put it in the viewWillAppear as others have suggested.

Why do I need to call addSubview if i'm immediately following it with addChildViewController [duplicate]

This question already has answers here:
What does addChildViewController actually do?
(4 answers)
Closed 7 years ago.
I'm pretty new to Objective-C and iOS.
I've noticed a familiar pattern in several apps, and I don't understand why it's necessary...
[someParentView addSubview:aChildViewController.view]
[self addChildViewController:aChildViewController]
From what I've read, you're not supposed to mess with a view controllers view directly, but rather just add the child view controller and the parent view controller will decide how and when to consult the childViewController's view.
In other words, when you've added a child viewcontroller to a parent viewcontroller, well obviously the parent viewcontroller has access to the child viewcontroller's view, hence calling addSubview seems not only redundant, but from what I've read, not recommended.
EDIT: Per a question below about more detail of what I'm doing...
I have a main storyboard view that covers the whole screen, and then I'm adding a view that takes only the left half of a vertical oriented screen. Users can tap on either the half view I added, or the remaining exposed half on the underlying full screen main storyboard view
Your main concern as I see is calling addSubview seems redundant?
I would say no it is not redundant, coz addChildViewController just Adds the given view controller as a child but it will not load/add the view.
This makes it essential to call addSubview
addSubview Add the child controller’s view as a subview.
For more info see:
Creating Custom Content View Controllers
Implementing a Custom Container View Controller
Refer the page, it will help you
http://www.objc.io/issue-1/containment-view-controller.html

UIViewController - where to put init of instance variables (using Storyboards)

I'm using Storyboards. I need to init instance variables of UIViewController just once. viewDidLoad and awakeFromNib fire each time I open a viewController from menu (I'm using SWRevealViewController for sidebar menu as in Facebook app). Is it normal for awakeFromNib to fire many times or is it SWRevealViewController bug?
So is there some special init method or do I need to set instance variables from outside of viewController (in AppDelegate?)
EDIT:
I found this question
SWRevealViewControllerSegue, reusing Viewcontrollers
I didn't realize that each time you show a controller via segue it creates a new instance of controller. So what does it mean? Does it mean that if I have a table of data loaded from web API - it will be reloaded each time I go back and forth through segue?.. Doesn't seem very effective to me. Is it normal for iOS?
View controllers are either recreated or reused depending on the situation. When you push a view controller onto a navigation controller's stack, you almost always push a new instance. When using a tab bar controller, the view controllers it contains are often held in memory. To avoid excessive memory consumption, it makes sense that view controllers are cleaned up when possible, rather than held around.
In the case of your SWRevealViewController then yes, it sounds as though your view controller should be recreated every time. You ideally shouldn't be directly loading any data from a web API within your view controller; instead, extract your API calls and models into separate classes that you can reuse from any view controller. Then, rather than reloading the data over the network when your view controller loads, you just need to fetch the latest data from your model / store class.

IOS - Disable View Cache in View Controller

I am pushing and popping from one view to the other within my App. The view is being retained in the memory so when you hit the "Back" button after pushing a view, the same screen that was before you pushed the view is retained.
For some reason, I will need to reload the parent view after popping from a child view. I need to display different content based on the actions the user taken when they were redirected to the child view.
I am using UINavigationController to navigate from one view to the other. I need it so I can easily go back and forth within the different views of the App.
The correct way to do this would be to perform your actions in viewDidAppear. Initialisation code that you write in viewDidLoad is called only once. But in viewDidAppear you can refresh your view's content every time the view is added to the window. The controller is retained in the memory for performance reasons. Removing it would hamper that factor.
Here is a stack overflow post that explains the different view* callbacks in good detail.

What's the difference between the RootViewController, AppDelegate and the View Controller classes that I may create?

I am trying to learn programming for the iPhone and I keep seeing these files and I am not sure when is each file and content of those files referred to in the execution of a program built for the iPhone. I am trying to follow tutorials and tips available online but nowhere is there a point by point comparison or something like that. It would be great if any of you could list a few basic differences like when is each file referred and what should ideally go into each file and so on. Thanks for your time already.
In general, delegates can be thought of as event handlers. Accordingly, the AppDelegate is the main event handler for your entire application. It is told when the application has launched, when it will exit, when a Push notification comes in, when the app has gone into the background, etc. One of those events - applicationDidFinishLaunching - is typically responsible for creating the application's window and adding views to that window.
In most applications, the view that is added to the window is actually controlled by a UIViewController. Each UIViewController is responsible for managing the appearance of one main view plus all of its subviews. For example, a UITableViewController is responsible for managing a UITableView (main view) and all of the UITableViewCells (subview) that are inserted into that UITableView. The UIViewController typically acts as a delegate (event handler) to the views it is responsible for. When a user taps a table view cell, a method in the UITableViewController is called. When the user swipes to delete a separate method is called.
A generic UIViewController provides the same basic functionality, but for custom views. For example, the UIViewController may be responsible for displaying a few text views and a button. The UIViewController would create its main view, the text views and the button view. The text views and button view would be added to the view controller's main view as subviews. The UIViewController would register itself as the delegate for events from the text view (for example learning when the user has finished editing the text in the text view). It would also register a method to handle a button press originating from the button it owned. When any of these registered events occur, methods on the UIViewController are called allowing you to take whatever action is needed.
The rootViewController is a specific type of view controller used with navigation controllers. If you want an application that has the typical iOS navigation view hierarchy, your AppDelegate would typically add a UINavigationController to the app's window. That UINavigationController is useless without actually having content to display. That is where the rootViewController comes into play. You are responsible for providing a view controller (such as the one described above) to act as the first view stored in the UINavigationController's stack of views. This view will be displayed when the app starts up and anytime that the user pops subsequent ViewControllers off of the UINavigationController's stack.
Long winded I realize - but hope it helps.

Resources