When I call performSegueWithIdentifier: I am overriding prepareForSegue: afterwards in order to set some properties on my destination view controller. However, I'm trying to understand the order of operations here to make sure it's safe.
I instantiate the destination view controller with:
MyViewController *myVC = (MyViewController*)segue.destinationViewController;
Afterwards I set a few properties on it - namely, I initialize the creation of another object which handles loading different web views, and then set properties on that object:
[myVC setFormHandler:
[[WebFormHandler alloc] initWithSelectedFormName:[self theFormName]]];
In viewDidLoad: of my destination controller, I then query the properties on this object, and use this to load the correct web view. Now, I am slightly confused by which happens first - the setting of the properties, or viewDidLoad: on the destination controller. Can it be said for certain that the properties of the view controller will always be set from prepareForSegue: before the viewDidLoad: is called?
It looks like you may have found your answer from that other post, but I just wanted to add one point of clarification.
The standard flow is
performSegue -> prepare -> loadView (in destination controller)
However, in popover segues, the destination view is loaded prior to the prepareForSegue call.
NOTE: This is no longer the case in iOS 8. In iOS 8, popover segue's views are NOT loaded by the time prepareForSegue is called.
Related
I have used protocol to send data between two view controllers without using storyboard.
ViewControllerB * viewB=[[ViewControllerA alloc] initWithNibName:#"ViewControllerB" bundle:nil];
viewB.delegate=self;
[self.navigationController pushViewController:viewB animated:YES];
How to impliment this with storyboard.
How to impliment this with storyboard.
There's less need to create a protocol to communicate between two view controllers when you use a storyboard. Typically, you'll use storyboard segues to transition between view controllers. When a segue is triggered, the current view controller will get a -prepareForSegue:sender: message, which has the segue as its first parameter. The segue has references to both the "source" and "destination" view controllers, so you can get a reference to the new view controller (the destination) and pass it whatever data you like at that time.
If you do still want to make the current view controller the delegate of the destination and let them use whatever protocol you can dream up, you can set the new controller's delegate in -prepareForSegue:sender:. The rest (creating the protocol, implementing it, etc.) is exactly the same as you've always done.
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.
I want to move from one view controller to the next, using code. I have this:
[self.navigationController pushViewController:ViewController2 animated:YES];
This code is used in the first screen that launches. I want it to push (under a certain condition) to the NEXT view controller which is called ViewController2. ViewController2 already exists (its a storyboard project). But the current view controller doesn't know what ViewController2 is in the above code. How do I 'get' or 'access' ViewController2? It already exits, with .h and .m files, but how do I call to it!?
if you're using storyboards, you can just access it through its identifier like this:
ViewController2 *viewController2 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
Make sure to properly set its identifier to "ViewController2" or whatever name makes sense.
This isn't the way that you normally push a view controller when you're using storyboards. You should have a push segue set up in IB and the use performSegueWithIndentifier:sender: to go to the next controller. You should also implement prepareForSegue:sender: where you can get access to both the source and destination controllers. This is the method where you typically provide any data needed for the second view controller to do its job.
I've been trying to understand for hours when I should use the viewDidload: and when I should use initWithNibName: to set up the properties of my viewController.
For instance, I'm using a TableViewController and I'm setting all its properties (such as the backgroundColor, the separateColor, the toolbar items) in initWithNibName. It is the right way to do ?
If somebody could enlighten me.
Thanks
You should set up your properties in the viewDidLoad. This method is called by the system when the controller's view is loaded into memory. The initWithNibName: is something that you call when you create a controller instance from a nib file.
That is to say, that if you set up your properties in the initWithNibName: and instead you call init, your controller might not be in a good state; thus, it's best to do in viewDidLoad.
You should use viewDidLoad: method of your controller. To quote from Apple's documentation on initWithNib:
The nib file you specify is not loaded right away. It is loaded the first time the view controller’s view is accessed. If you want to perform additional initialization after the nib file is loaded, override the viewDidLoad method and perform your tasks there.
initWithNibName: is called when the NIB is loaded and instantiated.
viewDidLoad: is called when your view is actually presented onscreen.
And yes - I believe that in your case, setting colors and such are best done in initWithNibName
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.