I'm starting an app where I'd like to have multiple view controllers. Some of the views will be displayed inside of a navigation controller. I can create a navigation controller and then add another instantiated view controller to it. But what I'd like to do, is just instantiate a view controller that has its own view and is the root view controller of a navigation view controller. So when I instantiate the view controller, I'd like for it create a navigation controller and push "self" on to it. When I do it my simulator crashes and the details don't really give a reason. The console does not display anything. Any ideas. My reason for this is to separate out logic without have a view controller that simply creates a navigation controller and then pushes another view controller on it as the root view controller.
I'm not entirely sure if I understand your question correctly. Why would it be preferable if the view controller pushed itself to the navigation controller? I mean, you have to instantiate your view controller at some point in code (either app delegate or another view controller) anyway. Why can't you just create the navigation controller there, instantiate your VC and then push it onto the nav controller? As far as I can see, this doesn't involve creating any additional view controllers.
Anyway, having a view controller decide by itself where it is used (ie. pushed onto), is not best practice. This way you lose the flexibility of using it in other contexts. Always try to couple your components as loosely as possible.
Related
iOS 5 introduces the concept of custom container view controller and provides API like addChildViewController. Question: can you add a view controller as a child and still present it using presentViewController? Does doing the latter automatically make it a child view controller of the presentingViewController?
That's not how it's supposed to be used.
The parent/child relationship is for when a view controller has subviews that are managed by their own view controllers, for example a UITabBarController, where the parent view controller draws the tabs and the child view controllers draw the content of each tab.
If you present a view controller using presentViewController, it generally takes over the whole screen, or appears in a modal so that the presenting view controller is no longer in control. In that scenario there's no reason for the presenter to be the parent because it doesn't need to cooperate with the presented controller - it just gets out of the way until the presented controller is dismissed again.
Why is it that you wanted to do this? If it's just so that the view controllers have a reference to one another and can pass data, there are other ways to do this (e.g. the delegate pattern, NSNotifications, or even just a property linking the two).
iOS5. I'm trying to create and add a new container view controller to my app - but need the parent view controller to itself be a child of the another view controller. Is this possible?
What I've tried so far results in the child and/or parent not being visible.
While I'm asking - has anyone got any good reference examples of creating container view controllers in iOS5. Btw, I've watched Apple's WWDC video.
Ok, well to answer my own question again, lol, No a Container ViewController doesn't have to be a root view controller.
My app structure is a navigation controller (let's call this vc1) with a variety of viewcontrollers pushed and popped on/off. One of these pushed view controllers (lets call it vc2) needs to have child view controllers. Originally I wanted to create a Container View Controller (let's call it vc3) and add this as a child of the pushed view controller and then add children to it (let's call this vc4 and vc5). This would have resulted in the following:
Nav Controller (vc1)
View Controller (vc2)
Container View Controller (vc3)
View Controller (vc4)
View Controller (vc5)
I couldn't get this working. So I had a rethink and tried combining vc2 and vc3. This seems to be working so far (I have got a visible view controller view).
My (so far) working structure is:
Nav Controller (vc1)
Container View Controller (vc2)
View Controller (vc3)
View Controller (vc4)
Let's say you have a tab view controller on the navigation controller view stack. (For the sake of argument.) Your tab controller has an array of view controllers for each of its tab views. Your tab controller's navigationController is clearly set to the nav controller (since its view is on the stack.)
But would you set the navigationController for each of your tab views to point to the nav controller? Their views aren't actually on the nav stack (they are subviews to the tab view that is), but it's necessary for them to be able to push a view onto said stack. Is it a bad idea? Should I do this but use a different instance variable?
Or would you just maintain pointers from all the subviews to their parent view controllers all the way up to the navigation controller? That seems clumsy and not that great if you have to go more than one level deep (which I do.)
(I'm not precisely doing this, I have a complex view with dedicated controllers for its subviews, so this is an accessible analogy.)
I find I am more successful when I keep separate navigation controllers for each tab. Then they can operate independently, and keep state when the user switches across tabs. Then there is no confusion about which view controllers are on the stack are below, or visible at a given point in time.
As for keeping pointers among the views and controllers, do not confuse the view hierarchy with the view controller stack, they are only orthogonally related as far as your view controller stack is concerned. There is a natural "ownership" of views by their view controllers, and you shouldn't have to be manipulating those pointers yourself, that should fall out naturally from the loading and creating of views, and view controller stack management API calls.
I have a Navigation Controller with a root table view which has several links. Tapping each link moves to the next view (by pushing it to the navigation controller's stack). But suppose that in that "next view", I have a UIButton that should take me further to another view (by pushing on to the same navigation controller's stack)...
View Controller-->first view-->second view-->third view..........
Now, I can easily access the Navigation Controller when I deal with the first view (and successfully push it to the Navigation Controller's stack) because it has been instantiated in the same file itself. What my real doubt is--How do you access a Navigation Controller in a far off view controller (eg, the third view or fourth view etc)? Please note that I am not using any separate delegate. All the Navigation Bar methods have been implemented in one file and connected to the Navigation Controller via an outlet.
When you push a ViewController onto a NavigationController the ViewController will automatically have it's navigationController property set. This means you can access the same NAvigationController no matter where you are in the stack.
-Update-
navigationController
In every UIViewController you can access that property.
So to in any other UIViewController that has been pushed onto the stack you should be able to just do this:
[self.navigationController pushViewController:othercontroller animated:YES];
Look at the documentation for UIViewController to see what other magic properties you have available.
Is my assumption that every controller which is presented with presentModalViewController:animated: need their own UINavigationController stack for their own hierarchy of drill down controllers? Meaning, say I have a top level controller It has its own navigation stack, and an action button which presents another controller via a modal. That modal has its own navigation stack. Is it best to split each modalView with its own Navigation stack?
If you want a modal view to have the forward-and-back behavior provided by a navigation controller, you need to provide a separate navigation controller for it. (If you don't need to push and pop view controllers inside that modal view, then you don't need one, of course.) This can be a bit of a pain, but them's the breaks.