Interplay between UINavigationController’s addChildViewController and topViewController - objective-c

I have something like a modal view controller that I need to display above my other view controllers. I’m not using the regular modal controller feature (presentViewController: and friends), since I need better control over the process. Instead I am using the view controller containment feature (the addChildViewController: method group).
The containment feature makes the code fairly straightforward. When I need to present the “modal” view controller, I add it as a child to the view controller hierarchy and everything works as expected. One small catch is that the regular view controllers are wrapped in a navigation controller. Therefore I have to add the modal controller as a child of the navigation controller, otherwise it would be covered by the navigation bar and toolbar.
Now the problem is that calling addChildViewController: on a navigation controller also sets the new controller as the topViewController, as if the controller was pushed using the regular pushViewController: method. This means that while the modal controller is displayed, the regular controller underneath it does not receive the appearance and rotation callbacks.
This feels like a bug, or am I missing something?

I had the same problem. I resolved this by writing my own custom view controller, containing a UINavigationController (added via addChildViewController:) and then exposing the UINavigationController as a readonly property. Then you can add your modal view controller as a child of your new custom view controller instead of as a child of the UINavigationController

I missed this sentence in the documentation for addChildViewController:
This method is only intended to be called by an implementation of a
custom container view controller.
So I guess it’s my fault and this scenario is simply not supported. Which sucks, because it’s very convenient to design whatever modal things as regular view controllers and connect them to the hierarchy like proper first-class citizens. I would probably have to rewrite the navigation controller on my own to have built-in support for this.

Related

Custom segue that 'finishes' early?

I'm looking to implement a custom segue that pushes to a UIViewController, but completes before the new UIViewController fully fills the screen, leaving some of the source view controller still in view and functional. (For example; new view controller covers half of the user interface).
I'm keen to use a segue rather than a view that is moved using CGRect, Quartz framework method, or similar, as constraints get messy really easily, unless a custom segue could utilise such methods(?)
Any pointers greatly welcomed! :)
For this task you would use a container view controller, which manages and displays the content of multiple other view controllers at a time while letting them interact with their views like normal. An example of this would be the UISplitViewController, which displays two view controllers' views at a time, one on each side of the screen. You can design segues that swap out one view controller of the multiple on display in a container view controller, similarly to the Replace Segue implemented by Apple to swap out a UISplitViewController's detail view controller (the one on the right hand side).

addSubview: re-writes the navigation stack?

I'm working on a app which uses the controller containment pattern as described in the View Controller documentation in the iOS SDK.
I've written the controller container, and it works great. My controller is basically containing two sub views and it displays them both at the same time, sliding one over the other depending on what the user is doing. Works wonderful.
Now, I want to use this container controller in a navigation view. This is to get push segues to work. In effect, from my contained controllers, I want to be able to use the navigation stack, push a new controller on, and pop when the user is done.
However, I have noticed that if the navigation view is instantiated with my container controller as the root container, things fall apart.
In particular, I have noticed this:
In the iOS documentation, container controllers call addChildController: and then addSubview:. This seems to break the navigation stack, as the push segue does not work - it behaves like modal. I believe it does this because addSubview resets the navigation stack.
I confirmed this by replacing addChildController and addSubview with [self.navigationController pushViewController...]. I confirmed it is a problem with addSubview because I can reproduce the issue when I omit the call to addChildController.
When I do this, the navigation stack works properly. But of course, my container controller does not, as only the "most recently pushed" controller is visible.
I'm doing this because in my contained controllers, I want to push a new controller onto the stack, and when the user is done, I want to "pop" the stack, without reloading the "previous controller".
Using a modal segue reloads the previous controller; using a push controller does not.
I cannot find any documentation on the behavior of addSubview and it's effect on the navigation stack.
Thank you in advance for any light you guys can shed!
I'm having a bit of trouble completely understanding what you are doing, but I think that what you want to do is exactly what I'm doing.
I have a UINavigationController that has as its rootView a container UIViewController. That controller adds children per the normal methods. One of those children views pushes other views that may get popped.
One of those pushed views COULD message the appDelegate and make itself the rootViewController if it wanted to. In general, as long as you keep a strong reference to a view controller, you can remove it from whoever 'owns' it, and muck around with the navigationControllers viewControllers array to your hearts content.

A view switching framework for "true" MVC on iOS

I don't like the UINavigationController because the tree/drill-down navigation style does not work in all situations. What I'm looking for is a sort of UISwitchController where a view controller can tell the UISwitchController what the next view is and the data to pass to it. Then the current view closes itself and the UISwitchController would handle opening the next view and passing in the data from the previous view. The UISwitchController could remember the name/type of the last view opened so the current view could tell who opened it (also allows the UISwitchController to handle a Back request by the current view without the current view specifying the name of the view that opened it). A view could also flag the UISwitchController to keep it in memory and not to release it after it closes so the view controller is essential reused for each call to that view. Is there such an framework?
So basically you are talking of a UIViewController that holds several UIView(Controller)s and handles the presentation.
In iOS < 5 I would just use a UIViewController, that adds views to another view, that is displayed.
in iOS 5+ you should familiarize yourself with UIViewController Containment, that is actually a pattern of how to use UIViewControllers with other child view controllers.
form the UIViewController doc
Implementing a Container View Controller
In iOS 5.0 and later, custom UIViewController subclasses can also act
as container view controllers. A container view controller manages the
presentation of content of other view controllers it owns, also known
as its child view controllers. A child’s view can be presented as-is
or in conjunction with views owned by the container view controller.
Your container view controller subclass should declare a public
interface to associate its children. The nature of these methods is up
to you and depends on the semantics of the container you are creating.
You need to decide how many children can be displayed by your view
controller at once, when those children are displayed, and where they
appear in your view controller’s view hierarchy. Your view controller
class defines what relationships, if any, are shared by the children.
By establishing a clean public interface for your container, you
ensure that children use its capabilities logically, without accessing
too many private details about how your container implements the
behavior.
Session 102 - Implementing UIViewController Containment — WWDC 2011
I haven't used it much so I don't know if it's exactly what you're looking for, but you can use TTNavigator from the three20 framework to do URL based navigation which sounds like it could be what you want.
https://github.com/facebook/three20

How to know Present view of UINavigation controller iPhoneSDK

i have one navigation controller, by using that i am pushing my view
here my problem is how to know that which view is presently appearing on my navigation controller
can any one of you give me the answer
Probably you want to look at the topViewController property of your UINavigationController (or perhaps its visibleViewController if you are using modal views). The current view would then be referenced by the view property of the returned controller.

SplitviewController as a subpage of a NavigationController

I am trying to have add a splitview as a subpage in UINavigationController hierarchy. I am guess this is possible, but not sure. Otherwise, I will just have to do similar functionality manually.
You cannot do that, a UISplitViewController must be the root controller of your app.
From Apple:
A split view controller must always be
the root of any interface you create.
In other words, you must always
install the view from
aUISplitViewController object as the
root view of your application’s
window. The panes of your split-view
interface may then contain navigation
controllers, tab bar controllers, or
any other type of view controller you
need to implement your interface.
http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/iPadControllers/iPadControllers.html#//apple_ref/doc/uid/TP40007457-CH6-SW2