What is the difference between view controller life cycle and view life cycle in iOS? - ios

Reading several tutorials and books on iOS development I often encounter terms : UIViewController life cycle and UIView life cycle. I'm interested: is there an actual difference between these two terms?
Looking Apple docs I found that methods such as viewDidAppear or loadView is a part of view controller's life cycle, but I think it is more correct to refer them as view life cycle and methods such as initWithNibName or dealloc as controller's life cycle. Or there is no such a separation and when someone speaks about view life cycle he actually means UIViewController life cycle?

Both are different concepts, therefore have different life cycles.
UIViewController
A ViewController is the Controller in a MVC architecture. Therefore, it is responsible to coordinate the info between the model (your data) and your views. UIViewControllers coordinate the UIViews and are part of navigation between screens (pushViewController, presentViewController). Therefore it needs to know when it will appear in the screen.
A UIViewController has a very specific life Cycle and it has methods that can be extended that are part of that life cycle. Examples of those methods are:
viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear
View
A View, on the other hand, shouldn't be worried when it has to appear on screen. Therefore, it has a complete different life cycle:
awakeFromNib, willMoveToSuperView, didMoveToSuperView
This methods usually are called in the sequence of the UIViewController's life cycle. Therefore, normally, the UIView responds to changes and people don't consider they have a Life cycle on their own.
The ViewController's life cycle only makes sense when a class extends UIViewController while a UIView's Life cycle only makes sense when extends UIView.
Most of the times, when people talk about Life cycle they will talk about the UIViewController life cycle, since the View usually responds to changes. Two examples of those changes are: the view changed its size, changes its parent.

All your confusion will go away once you fully realise the difference between the two classes and ingrain it into your mind (by practice)
UIViewController - a class that has no UI in itself (not completely true though...see root view), its purpose is to control views and do some related stuff..It is like a policeman or traffic controller policing others. (views).
Most of the time you create your own subclass of UIViewController and that class tends to be quite heavy on functionality like
handling logical rules when to show what view
connecting to model layer (data and facts about the problem your app is solving)
interacting with other controllers,
UIView - a class that represents a rectangle area that can be heavily visually modified, but the most important fact is, it is visible on the screen, and can have subviews, which are also UIViews. Views are organised into view hierarchies.
Most of the time you customize your view so that it is
visually pleasing
handles it's subviews via autolayout
represents the particular type of visual information you need often subclassed to a more specific view class like labels, texts, buttons, etc.
One bit that confuses newcomers is that every view controller has one root view, a property which holds a UIView instance. Often you can get lost as to whether this root view is discussed, or the view controller is discussed. In causal discussion between developers, the two words are sometimes used interchangeably.
Both controllers & views have the lifecycle but you must not confuse the two.
ViewController lifecycle is what happens to the controller itself, like it awakes from nib file, or receives a low memory warning, but mostly about how its root view comes to life, how it appears disappears and dies..
View Lifecycle is about how the view lays out its subviews, and how it renders its content.
I like visual analogies..
Simply imagine a policeman with a lot of colorful paper rectangles. The policeman is the controller, and he says what (views) is shown and when on the screen.
The controller and the View are abstractions that are part of (Model View Controller) MVC architectural pattern. I recommend you study that immediately, so that the problem with lifecycle confusion is further cleared in your mind.

Adding to these answers and focusing a bit more on your exact questions:
I'm interested: is there an actual difference between these two
terms?
Yes, there is a different between both, but in a context where you are dealing with a UIViewController's root UIView, they are in a way related.
Looking Apple docs I found that methods such as viewDidAppear or loadView is a part of view controller's life cycle, but I think it is more correct to refer them as view life cycle and methods such as initWithNibName or dealloc as controller's life cycle.
And this is why they are related:
viewWillAppear
viewDidAppear
viewWillDisappear
viewDidDisappear:
They are all under Responding to View Events in the documentation. So these are callbacks from the UIView to the UIViewController telling it about its state. And although:
loadView
viewDidLoad
Are not under the same section (in the documentation), it's the UIView requesting/telling the UIViewController about its current state. And you have other examples of these interactions, for example:
viewWillLayoutSubviews
viewDidLayoutSubviews
In a way (and in your question's context) the general answer is: yes, those are two different lifecycles with different particularities, but they are related in a way. An example where they are not directly related would be the UIViewController's didReceiveMemoryWarning. (I say directly, because indirectly, it might be the UIViewController's root UIView the culprit).

Most of the lifecycle is handled automatically by the
system and no need for calling some methods like parent and child view
controllers relationship
Here are the mentioned lifecycle methods for UIView:
didAddSubview(_:)
willRemoveSubview(_:)
willMove(toSuperView:)
didMoveToSuperview
willMove(toWindow:)
didMoveToWindow

Related

Is it better to have a viewDidLoad in all view controllers or just in the main view controller have multiple UIViews?

For now I have a single login view controller that hide and adds subviews dynamically based on user interaction. Is it better to have multiple UIViews with one view controller, or multiple view controllers?
The benefit of having children UIViewControllers would be if you needed to care about the view lifecycle in any of the children. For instance, if in some of your subviews (child views) you needed to know if it appeared to trigger some logic, then it would be good to use children UIViewControllers.
Another reason might be, if you wanted to use view controller transitions within your custom container, as described by Apple in the UIViewController class reference:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/transitionFromViewController:toViewController:duration:options:animations:completion:
But, to me it doesn't sound like you would need this, it sounds like you would just show/hide your views, or otherwise animate them.
But if your views don't care about any of that, and just need to render UI elements, I'd say using children UIViewControllers adds additional complexity without much benefit.
This is under the assumption that either way, all your views are living on the single UIViewController's view. If you are pushing and popping view controllers inside a UINavigationController, or presenting ViewControllers modally, you definitely should use UIViewControllers for that.
Also, you definitely shouldn't put all your view code inside that single view controller. You should use subclasses of UIView, or some other mechanism of making sure you separate your components.
For example you might have:
LoginViewController - organizes and hides and shows the individual views
SignInView - shows the sign in form
RegisterView - shows the register form
...etc
Of course its better to have multiple view controllers for many reasons:
Each view controller has its own code/logic/functionality.
Better for memory management. Once you're done from a view controller, system will automatically deallocates it from memory. Using multiple views will be overload in your system when some views are not used.
Better organisation for your project. You will just present/dismiss/push/pop view controllers and pass data between each other. Instead you will deal with horrible logic for hiding and showing UIViews.
Using one view controller will have a massive amount of code which in long term the project will be an impossible mission to manage.
Having multiple view controllers is better in the sense that you would have more ease at coding them individually. Also Navigation will be good which is good for User Experience.
Memory Management will be efficient.
The MVC architecture(Model View Controller) will instead become Massive View Controller which will be a headache while debugging.
Check out this answer for more clarity. I think you are confused between ViewController and View.
Check out the accepted answer of this question in the link. Hope it helps.
About viewController's "viewDidLoad" and "viewWillAppear" methods

A debatable delegate-like event notification pattern

I was left with continuing the code of a senior developer, where I came across a coding pattern that was not only bizarre, but got me curious about a lot of things. The pattern, however, that I spoke about had something like this:
There is a UIViewController the view of which has an instance of extended UIView attached to it as a subview.
This custom UIView class has a reference of the above-stated UIViewController.
There are a series of methods defined within the UIViewController that are responsible for handling events at the UIView.
Since this UIViewController exists as a reference, our custom view calls those event-handling methods through this reference!
In such a system of code, what are the memory implications? How is this any different from the delegate pattern? Under what circumstances using this sort of coding okay?
While this pattern is a little curious, I would hesitate to condemn this without more information about what this child view is doing and what it needs to inform the view controller about. There is, admittedly, a faint code smell here, and if I were to hazard a guess, I'd bet that this view is likely doing stuff that one would now generally put in a view controller.
Often, when adding a subview that has any significant complexity (or is likely to be reused in different views), one would consider an iOS 5 feature, "view controller containment" (see the Creating Custom Container View Controllers section of the View Controller Programming Guide or WWDC 2011 video Implementing UIViewController Containment).
If using storyboards, you can achieve much of this using the special "Container View" control introduced with iOS 6, found in Interface Builder's "Object Library" (in the bottom of the right panel in the standard Xcode layout). If doing this programmatically, just make sure to call the appropriate methods listed in the "Managing Child View Controllers in a Custom Container" section of the UIViewController Class Reference.
When using view controller containment, you have a parent view controller (the main view controller) and the child view controller (the view controller that is managing the subview). And in this scenario, it's very common to design a custom protocol by which a child view controller notifies its parent view controller of particular events. But rather than adding your own custom delegate property, you can use the built-in parentViewController property which is automatically populated when you adopt the above "view controller containment" pattern.
Having said all of this, I might let practical concerns drive whether the existing code base needs to be refactored or not. Perhaps the code predates iOS 5, but is a solid implementation of what we might have done back in the day. Bottom line, if it works, is otherwise well written, and has the delineation of responsibilities clearly defined, you might decide to just leave well enough alone. And if it's a little ambiguous (as the absence of a discussion of a protocol might suggest), perhaps just start by introducing a formal protocol between the child view and the view controller to make the interface explicit. Whether a more radical refactoring of the code (to use something like view controller containment) is called for is hard for us to advise on the basis of the limited information provided thus far.

Need advice regarding multiple child view controllers

All,
I am running into some performance/memory issues when using several ChildViewControllers in my ParentViewController. Here is my situation: I have a ParentViewController with a dynamic number of ChildViewControllers - some times as many as 20. They are contained in a UIScrollView, and are paged through. I'm running into problems when I have several on the page (I'm only loading the first two, then building the others as I swipe), however, having that many within the ParentViewController is starting to cause some crashes due to memory.
The ChildViewController has a lot going on in it, and I'm going through it to make sure it's as efficient as possible, however, I have concerns about this approach working on older devices (as is, I'm getting crashes on the 5S).
It seems that it would help to change the view controllers to just be views, but it'd be a pretty large endeavor as the VC is complex. One suggestion I had was to create a view from the existing view controller's view, and set several delegate methods on the view and interact with the views from the ParentViewController that way. Does any one have any thoughts on the efficiency of that method as a opposed to the current method of using ChildViewControllers?
Another thought I had was to build a custom ContainerViewController and have all the children in there to swipe through, but I wasn't sure if that would give me an advantage over using the children in a UIScrollView.
Any thoughts?
I personally would not advocate the refactoring of your code to use views rather than view controllers. The view controller, itself, is unlikely to be the source of the memory problems, but rather the model objects they keep track of (as well as the assets the view controller's view uses). I think the key is to simply remove the view controllers (and their views) as they scroll off of the screen.
In your scrolling logic, as you're adding child view controllers that scroll into view, you are presumably doing all of the appropriate containment calls:
UIViewController *newChildViewController = ...
[self addChildViewController:newChildViewController];
newChildViewController.view.frame = ...;
[self.scrollView addSubview:newChildViewController.view];
[newChildViewController didMoveToParentViewController:self];
(See WWDC 2011 video Implementing UIViewController Containment for a discussion about why it's important to do these containment calls, namely to keep your view controller hierarchy synchronized with your view hierarchy.)
As the child views scroll out of view, you just do the appropriate containment calls to remove the child controller (and its view):
[childViewControllerToRemove willMoveToParentViewController:nil];
[childViewControllerToRemove.view removeFromSuperview];
[childViewControllerToRemove removeFromParentViewController];
// also remove any other strong references you have to that childViewControllerToRemove
Alternatively, you might want to contemplate using a UIPageViewController which (in iOS 6+) offers scrolling page view (UIPageViewControllerTransitionStyleScroll) for the transitionStyle. This simplifies the amount of custom container code you have to write to handle the view controllers that scroll in and out of view. The UIPageViewController is designed precisely for this situation of scrolling (or paging) through a bunch of different view controllers' views. See the Page View Controllers discussion in the View Controller Catalog for iOS.
I don't think moving them all to UIView's will help. You could achieve this same effect by just adding aChildViewController.view without ever technically adding it as a childView. I would optimize the loading of the views into your UIScrollView. Make sure you only have, say 4 views loaded into memory at any one time. Another option would be to use a horizontal UITableView or UICollectionView so you can reap the memory management features they have build in.
You could turn it into a tableview and let the cell dequeue take over. You would only have a few in memory at a time then.

transitionFromView:toView:duration:options:completion: confusion

I am trying to utilize transitionFromView:toView:duration:options:completion: but in uiview class reference this point is confusing me. What it means?
This method modifies the views in their view hierarchy only. It does
not modify your application’s view controllers in any way. For
example, if you use this method to change the root view displayed by a
view controller, it is your responsibility to update the view
controller appropriately to handle the change.
Please view the sample project https://anonfiles.com/file/521cbb41b086eae987fe27eb98278aba
In this project I just called transitionFromView:toView:duration:options:completion: and everything is working fine and did nothing what is mentioned in the above point.
You are more likely asking for an explanation of Apple's documentation than a specific question, if I understand your posting correctly.
Nevertheless I'll give you this explanation and I hope, it will help you:
You write:
Everything is working fine..
and that is, because you a doing well here!
According to the MVC design pattern (Model-View-Controller), you are using the classes UIViewController (the "C") and UIView (the "V") in your code.
A view contains the visual representation of objects (like labels, buttons, subviews, ...) without an logic for their behavior.
A viewcontroller provides the logic, e. g. IBAction methods and any other methods that you may implement.
Each UIViewController has its own "view" property containing the view, whose behavior the controller does manage. This view normally contains additional views, e. g. labels, images and buttons. They are subviews and are stored in the view's "subviews" array property. Btw, each view has such a subviews property - that is, how we can implement complex view hierarchies.
In your situation (multiple subviews that are managed by one common viewcontroller), the method
transitionFromView:toView:duration:options:completion:
hides "fromView" and unhides "toView" with the support of animations. It is a transition between to views. The paragraph from the documentation shall prepare you as a developer, that this method only manages the change of the visual representation and does not provide additional "services" for your view controller for the further management for the participating views.
That means, that you have to manage e. g. the state of the views (which view actually provides interaction for the user) by your own code. It seems to me, that you have managed this well!
In a wider scope, iOS supports UIViewController container as well - they can contain child view controllers (which again contain their view with its subviews). In such an architecture, there is another transition method from the SDK,
transitionFromViewController:toViewController:duration:options:animations:completion:
which allows you to implement transitions not between two views, but between two view controllers.
I hope this is not too much text and helps to make things clearer for you.

viewWillAppear versus loadView for building view hierarchy

I'm constructing my view hierarchy through code and would like to know if it's better to create the entire hierarchy in loadView, when the view is requested from my controller, and then animate the views onto the screen in the viewWillAppear method, or if it's better to keep things simpler but potentially require more freeing and allocating of memory by building the entire hierarchy in viewWillAppear.
My understanding is that the controller calls loadView to create the view the first time it needs it, then keeps it around as long as it can so that you can leave and return to this controller and animate in the views, but not need to recreate and attach them, via viewWillAppear.
Basically, I'm finding it messy to be separately allocating the views in loadView and then transitioning (and sometimes updating the contents within) them in viewWillAppear, and wondering if the benefits of retaining the views don't outweigh the simplicity of simply recreating them (and consequently re-initializing them and avoiding any un-reset values).
loadView is called only once at the creation and should contation everithing to create the view.
viewWillAppear:(BOOL)animated is called everytime the view is displayed. If your view was retained, you can update/set your data in this. (Your UIButtons, UILabels,... are already allocated by loadView, you just set the content here.)

Resources