UIWindow and UIView addSubview Question - objective-c

Does the addSubview method actually load the view into the application or not? The reason I am asking is because I have two two views in my application. The application delegate adds the two views as subviews and then brings one of the views up front. Now, I have a print statement in each of the viewDidLoad methods for each view. When I run the application, the application delegate loads the views as subViews and as each view is loaded, I actually see the console print out the statements that I placed in each of the viewDidLoad methods. Is this supposed to be doing this?

viewDidLoad is actually a method of UIViewController, not UIView. It gets called after the view gets loaded into memory (after your init method, but before the awakeFromNib). You'll notice that addSubview: takes a UIView as a parameter, so the view must have been loaded in order for the view to be added to another view. Otherwise you'd be trying to add an imaginary view.
In answer to your question, yes it is supposed to be doing this. viewDidLoad is called long before you addSubview. In fact, if you take out the addSubview: lines, you'll notice that it's still getting called (because you're creating the view's controller).

My understanding is that views are lazily loaded. If your viewcontroller has 10 view, they are not all loaded until you actually try to access them.

Related

Should we call ads in viewDidLoad or viewDidAppear?

We have a tab-heavy app, which has 5 tabs to use back and forth. We have iAds and admobs(as backup for countries without iAd), and we 'call' the ads in viewDidLoad. Would it make a difference to call them in viewDidAppear instead? And then remove them in viewDidDisappear or shomething not to screw up the frames etc? Would this give more impressions etc?
viewDidLoad:
viewDidLoad
Called after the controller’s view is loaded into memory.
- (void)viewDidLoad
Discussion
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.
viewDidAppear:
viewDidAppear:
Notifies the view controller that its view was added to a view hierarchy.
- (void)viewDidAppear:(BOOL)animated
Parameters
animated
If YES, the view was added to the window using an animation.
Discussion
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
Answering
So viewDidLoad is called slightly earlier than viewDidAppear: , the only difference is that when viewDidAppear: the view have been already drawn, instead in viewDidLoad the view has still to be drawn.
So answering to your questions:
Would it make a difference to call them in viewDidAppear instead?
If calling the ads is a slow operation, then you would see first the view appearing in it's color, and the ads after a few interval of time.However this has to be too slow to make a real difference.
And then remove them in viewDidDisappear or shomething not to screw up the frames etc?
It doesn't "screw up frames", that for sure.
you just need call it in viewDidLoad
Putting your ad code in viewDidAppear: (and removing it in viewDidDisappear:) will certainly give you more impressions, but unless you're a whitelisted pub, you're probably getting paid on a cost per click basis anyway (AdMob Help Center article).
In this case, instead of having the overhead of creating and destroying GADBannerView objects on tab changes, you might as well create a singleton GADBannerView that you use throughout your TabbedController (look at an example here).

When will viewWill/DidAppear/Disappear is called anyway and how exactly does it work?

I understand that viewWillAppear will be called when duh.... when the the view is about to appear.
But how does IOS know that a controller's view is about to appear?
When exactly that and how it is implemented?
For example, does the childController.view check first that window is one of it's super ancestors? Does the view has a pointer to it's controller? How exactly that works? Does everytime a view is added it check whether it's window is it's super ancestor and whether it is the view outlet of a UIViewController?
For example, if I add childcontroller.view but not to a subview of any view that's being called. Will viewWillAppear called?
Does the childController need to be the a child of a parentController so that viewWillAppear of the childController will be called when the parentController's viewWillAppear is called automatically?
The view is loaded by your controller using the - (void)loadView method. This method is implemented to load a blank view or a view from a nib/storyboard. You only need to override it if you really need to create a view hierarchy from scratch.
All of the magic happens when the value of the view property is first requested and the controller detects the value is nil. All of the life cycle method calls are handled by the UIViewController. There is nothing you need to do other than implement the methods if you need them. Remember one thing: There is no guarantee the view has been loaded until the - (void)viewDidLoad method has been called.
Everything I've learned about controllers how they work has come from the View Controller Programming Guide.

What is called when removing a view from its superview?

Imagine I have a view controller called blueView and another called greenView. I then add greenView.view as a subview of blueView.view. Now suppose that after some user interaction, I'd like to remove greenView.view from blueView.view using:
[self.view removeFromSuperview]
What is actually happening here? Is blueView.view ever redrawn? I thought the viewDidLoad method might be called, however after putting an NSLog messge in viewDidLoad, it was never called after removing the subview. Any clarification as to what is actually happening when you remove a subview from its superview would be much appreciated.
First, a view controller is meant to manage an entire view hierarchy at once; you shouldn't have two view controllers (other than container controllers like UINavigationController) active at the same time. See this SO question and my answer to get a better understanding on this important point. So, the particular situation you describe shouldn't come up. (Aside: people often confuse views and view controllers, so it's not helpful to give your view controllers names ending in "-view", like "blueView." Call it "blueViewController" to help avoid confusion.)
Second, as #InsertWittyName points out, -viewDidLoad is a UIViewController method, not a UIView method. Taking that a step further, neither view controllers nor -viewDidLoad has any role in adding or removing subviews from a view. -viewDidLoad is called when the view controller's view is first created. It's basically just a way of deferring the view-related part of view controller initialization until after the view hierarchy has been created, so there's no reason that it'd be called again just because a subview was removed from the hierarchy.
Finally, exactly how a view removes itself from its superview is really an implementation detail -- it might call a private UIView method on the superview, or it might modify the superview's list of subviews directly, or something else. I don't see anything in the documentation that explicitly says that the superview will redraw itself after a subview has been removed, but in my experience the superview does indeed redraw itself. You can check this by putting a breakpoint on the -drawRect method of the superview.

Modal view controllers calling other's "viewDidLoad"

I have a bunch of pages I am chaining together and presenting as modal view controllers. THey all have viewDidLoad methods. It seems that when one is loaded though it calls the viewDidLoad methods of ones in the background too. How can I stop this? Thanks!
You can't. The viewDidLoad method will get called when the view is loaded. Asking a view controller for its view loads the view.
Consider moving code into your viewWillAppear:(BOOL)animated method. That way it will only get called before the view is actually shown to the user.

The relationship between UIViewController and UIView

I'm trying to understand how these two are connected. Every time you make a UIViewController does it also automatically come with its own UIView?
Also are these from Cocoa or Objective-C?
UIViewController is a Cocoa Touch class built for the purpose of managing UIViews. It expects to have a view hierarchy, but you don't "automatically" get a view (this is slightly inaccurate; see edit below). Usually you will obtain views by calling initWithNibName on your view controller.
There is some built-in magic in Interface Builder which knows that if File's Owner is a UIViewController (or subclass), there is a property called view. That's about it.
Once you have linked a view controller and a view, the view controller does a fair amount of work for you: it registers as a responder for view touch events, registers for device rotation notifications (and handles them automatically, if you wish), helps you take care of some of the details of animation, and handles low-memory conditions semi-automatically.
Edit: correction—if you don't call initWithNibName or set the view property manually, the view property getter will invoke loadView if view is nil. The default implementation of loadView will see if you've set nibBundle and nibName and attempt to load the view from there (which is why you don't have to call initWithNibName, most of the time), but if those properties aren't set, it will instantiate a UIView object with default values. So technically, yes, it does automatically come with its own UIView, but most of the time that's of little value.
UIViewController doesn't automatically come with a view. You have to make a view in the -loadView method. By default, this loads the view from the nib file you've specified. You can also override this method to make a custom view if you prefer not to use a nib.
Also, the view is not created right when the UIViewController is created. UIViewController uses a technique known as lazy-loading to defer the creation of a view until the view is actually accessed for the first time.