views:

190

answers:

3

I'm tinkering with an iPad app that (like many iPad apps) doesn't use the UINavigation root view control system, so I don't have natural ownership for each app "view". I essentially have two basic views: a document list view, and a document edit view.

I'm playing with UIView animation for getting from a selected document to the edit view.

I also have a toolbar on top that exists (with different buttons) in both "views".

Because I don't have UINavigation running the show for me, I have a tendency to just throw more and more stuff into one NIB and one view controller that owns the whole container. But now I'm trying to figure out how to segue from the document list view to the edit view if the edit view lives inside a different NIB, preserving the toolbar too.

Anyone have thoughts or experience on app structures like this? I find the docs lacking on best practices around code/UI structure for anything except trivial one-screen apps or full-on navigation apps.

You're not "supposed" to have parent/child view controllers owning subcomponents of the same "screen" according to the docs, but this implies one massive honking view controller that basically contains the whole app, and that can't be right.

Not sure if there's a "right answer" to this; I'm looking for some intelligent examples or suggestions. Nobody's touched this question in months, so I'm adding a bounty to generate good chatter. :)

Thanks!

UPDATE: I'm not talking about a split view, which is clearly well handled by a split view controller. Instead, take a look at Apple's iWork apps (e.g. Pages) which have a document list view and an independent edit view, but these are related by animation.

Maybe the real question here is: how would you (or could you even?) build a "container" view controller like the split view or navigation controller, yourself? Are you required to build the whole damn thing from scratch? I sense that you are, because seems to be hidden wiring in the interaction between view controllers. If so, thoughts on this?

+1  A: 

You need a master-detail view implemented with a split-view/popover-view and controlled with a UISplitViewController.

The master view is the document list and the detail view is the edit view. Each has its own controller. The two controllers themselves are managed by the UISplitViewController.

If you don't use the splitview controller you will just end up hand coding something that works very much like it. This is really the only way to do what you want easily in the API and it is the layout that iPad users will expect.

See Creating a Split View Interface in the iPad programming guide for details.

TechZen
Thanks for the answer, but I'm looking for some deeper architecture thoughts, as the split view is well known and simple to use. Apple's own e.g. Pages has a list/edit view design but does not use a split view-- what would be the best way to design for that?
quixoto
+2  A: 

I haven't tried the multiple-view-controllers thing outside of the UIKit-provided ones (navigation/tab-bar/modal/etc) but I don't see why it shouldn't work. Under the hood, everything is a view, though I'll note that UIKit has special views for view controllers which no doubt have some kind of special handling by the system (UIViewController has a wrapper view, UINavigationController has a UINavigationTransitionView or something, ...).

I'd advise not worrying too much about "best practice" — just code something which does what you want. A couple of options:

  • Stick logic into view classes (ewwww!). One of our apps does this so it can handle rotation in a custom way (views slide in/out instead of rotating). We should've probably implemented our own view controller logic instead.
  • Break the model into components which correspond to views. Make each view know how to load its component and recursively load subcomponents. Then the view controller only needs to worry about "big picture" stuff.

Also note that you can load multiple nibs into the same view controller by e.g. connecting it to an outlet called editView.The big difference is that it's not done automatically by -[UIViewController loadView] so you need to do something like

-(EditView*)editView {
  if (!editView) {
    // Loads EditView into the outlet editView
    [NSBundle loadNibNamed:@"EditView" owner:self];
  }
  return editView;
}

You'll also need to worry about adding it to your view hierarchy, unloading it on -(void)viewDidUnload (iPhone OS 3.0+), setting it up in -(void)viewDidLoad in case there was a memory warning during editing mode, etc...

It's not easy, but UI never is.

tc.
What I'm really after is, all this final stuff you mention about needing to load/unload yourself to work around the view controller's ownership-- I guess nobody's come up with a repeatable pattern for this? I have made this work by "hacking around" everything, but it's a bummer that only Apple gets to define "container" view controllers.
quixoto
+2  A: 

I think the only hidden wiring in view controllers is setting parentViewController, which is required to support the categories declared for split and navigation.

View controllers are designed to be nested, with each controller owning a part of the view hierarchy. The only design goal is that no view controller reach into the view hierarchy of another controller. A parent view controller will usually have some call for adding child controllers so that it can set the frame of the view within the view hierarchy it owns. A child view controller should not do anything to the superview of the view it controls, as that is owned by another controller. Not should it set the center or frame of the view it controls.

For example, a navigation controller has a push method, in which it removes the previous controller view, adds the new controller view, and sets the frame of the newly added view. In general, a parent view controller is free to set the frame of the view of a child controller, but not the bounds.

If you want to change the animation of a navigation controller, I think you would start by implementing every method with an animated: argument. Set up your animation then call super with the animated flag off before committing the animation.

drawnonward
Good info. I'll dispute your claim that view controller are designed to be nested. They're not, at least not by external developers, according to Apple's docs here: "If you want to divide a single screen into multiple areas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subsection of the screen. Then use a single view controller object to manage the generic controller objects. The view controller coordinates the overall screen interactions but forwards messages as needed[...]."
quixoto
(Reference is here: http://developer.apple.com/iphone/library/featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html#//apple_ref/doc/uid/TP40007457-CH112-SW10)
quixoto