SplitviewController as a subpage of a NavigationController - cocoa-touch

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

Related

UINavBarController connecting the same UIViewController to multiple navigation controllers

I have a storyboarded app with a chain of tableviews followed by a detail view. Kind of the classic iPhone app. There are 4 tabs and each one leads to a navigation controller.
The issue is I really want to avoid unnecessary glue code since the app is basically finished. If it was possible to connect the Search and Favorites (bottom two off the tab bar) controller as 'Root View Controllers' to the same UIViewController I would be done. However, this won't work since a view controller can only be the root view controller to one tab. So as you can see I've instituted two dummy UIViewControllers that forward you to the UIViewController in the middle. Now, unfortunately, I have to write code to make that central view controller a fake root view controller to disable the appearance of the back button, and prevent popping to the blank root when you double-tap the tab bar.
Has anyone got a more elegant solution?
This appears to be a flaw in Storyboards. One workaround would be to use simple view controllers for each navigation controller's rootViewController. Put a UIContainerView in each that points to the UIViewController you want to share.

Storyboard with NavigationController and TabController

It seems like this should be easy to figure out, but I haven't had any luck this afternoon. I threw together this quick, simplified storyboard mockup of my problem.
Basically, I would like the table view controllers below to also be in a tab bar controller (in addition to the already present navigation controller). The tabs would switch between the two table view controllers.
Right now, the view controller with the buttons acts as a sort of menu. Each button leads to one of the table view controllers. Ideally this view controller would not have the tab bar visible, and would only be reachable from back buttons on the nav bars of the table view controllers.
I've tried a few different ways of embedding into a tabbarcontrollers but none of them produce the desired result:
-I've tried selecting both table view controllers and embedding those in a tab view controller. The tabbar doesnt show up in simulator, and the 'unreachable scene' warning appears.
-I've tried embedding the initial nav controller into a tabbarcontroller. This creates a tab entry for the first 'menu' page. It also causes issues with push segues once I connect the tableviews to the tabview.
I would be fine implementing some programmatic options on top of the storyboard, I just chose storyboarding for this project since it's a relatively simple presentation of data.
What is the proper way of going about this? Thanks!
A tab bar controller needs to be the root view controller of your view hierarchy. It goes against the HIG and Apple's standards to put a tab bar controller inside of any other type of container controller.
From the Apple docs:
When deploying a tab bar interface, you must install this view as the
root of your window. Unlike other view controllers, a tab bar
interface should never be installed as a child of another view
controller.
So, the bottom line here is you need to rethink your design. One option would be to set the UITabBarController as the root view of your window, and then have each of your UITableViewControllers inside of a UINavigationController, which is placed inside of the UITabBarController. In this way, you still get the navigation bar, and stay within Apple's design guidelines (you also won't get those pesky warnings, and Apple may even be throwing an exception nowadays if you try to install a UITabBarController as anything other than the root view of the window).
I accept JMStone answer but we might get into situation where we need to put tab bar controller inside other controller especially table view controller.
Please refer Storyboard navigation controller and tab bar controller
and also the good example by Matthjin: http://cl.ly/VQLa
Hopes it help some one who want to put tab bar controller inside table view controller and wants proper navigation.

Interplay between UINavigationController’s addChildViewController and topViewController

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.

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

iOS 5 storyboard, programmatically determine path

I'm having trouble to achieve the following using a storyboard:
When setup is not done:
run app -> show settings view controller -> show main navigation controller
When setup is done:
run app -> show main navigation controller
So basically, I want the app to programmatically start with the settings view in certain cases, and otherwise skip right ahead to the main navigation controller.
I did manage to show the settings view with a modal style segue from the main navigation controller, but I don't know how to display it before the main navigation controller is displayed. Any ideas?
By default, the initial view controller from your main storyboard is instantiated and displayed automatically when your app starts up. To prevent this happening you need to remove the UIMainStoryboardFile setting from your info.plist file.
With no default view controller, you are now free to create one programmatically at app startup. See the UIStoryboard documentation. Use +storyboardWithName:bundle: to load the storyboard and then use –instantiateViewControllerWithIdentifier: to create the correct view controller. You will also need to create a main UIWindow and add the view controller's view to it just like you used to do with .nib based UI. Note that without the UIMainStoryboardFile setting a main window is not created for you - read the explanation.
I managed to do it a bit different:
Use a UINavigationController as the initial view controller.
Create a root view controller that will manage the decision of what to load.
Create a Storyboard Segues from the root view controller to the main view and to settings view, and give the segues proper identifiers.
Call the performSegueWithIdentifier with the proper identifier from your root view controller.
Just another solution, hope this helps.
I did something similar to amoshaviv, his advice is sound. I did it slightly different though, and I'll give some more info.
I created a custom MyInitialViewController class, derived from UIViewController, and made this the initial view controller.
In the storyboard file, I created modal segues with appropriate names to all (in my case three) possible 'real' first view controllers.
In the MyInitialViewController class, I implemented the
- (void)viewDidAppear:(BOOL)animated;
method, to first perform the check which view to switch to, and then do the correct
[self performSegueWithIdentifier:#"NameOfSegue" sender:self];
Effectively, this makes the MyInitialViewController nothing more than a switch performed when it's brought into view. I first tried doing this when loaded because I don't care for actually seeing this view, but that did not work, while viewDidAppear does.
To make this visually smooth, I tried the following. In the properties of the segues, I disabled animation. The view I left empty, and I gave it a background color matching to that of the startup image.