17

Ive been tearing my hair out over the last couple of days trying to understand this one seemingly basic concept of iOS development:

  • If I want to have two or more View Controllers displayed and usable in the same "screenful", is this:

    1. Not advisable as per Apple's "One VC per screenful of content"
    2. Completely possible by adding the VC's via code
    3. Just not done. Instead, use one VC and simply add code that mimics the functionality of the view controllers you want.

Let me rephrase a bit:

If I wanted to have, in an iPad app, a UIView (A) that takes up a large portion of the left side of the screen, and a second UIView (B) that takes up the rest of the right side of the screen, and I wanted to add a button to UIView B that when clicked would use the Modal transition to slide up a UITableview to replace UIView B, and this UITableview would then act like a typical UITableviewController whereby when the user picks an item from the table, the typical events are sent to the tableview controller to push in a new set of items, is this possible?

It just seems to me that if Im already able to easily create two separate UIViewControllers, and have a button in one VC modally bring up the second VC, why cant I combine this functionality so that one VC has two children VCs, and those children VCs handle their own modal transitions.

Or is the best practice in a case like this to simply have one VC that handles everything, and then manually handle animating the slides in / out of various views after various clicks on various UI elements?

As you can tell, I think Ive read too many different, conflicting responses to questions similar to this that Ive gotten entirely confused about whats what anymore. If anyone out there understands what Im getting at and can lend a helping explanation or some pointers Id greatly appreciate it.

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
Adam Eisfeld
  • 1,424
  • 2
  • 13
  • 25
  • Did you find a good way to do this in iOS 5? The problem I'd like to solve is well defined in your reference http://www.tumblr.com/tagged/child-view-controller. It sure would be nice to nest the various pieces inside a master view to keep the master view from becoming code heavy. – mm2001 May 26 '12 at 06:38

3 Answers3

11

The answer depends on whether you need to support iOS 4 or not. If yes, the answer is:

Answer number 1 - With the exception of Apple's own container controllers, notably UITabBarController, UINavigationController, UISplitViewController, UIPageViewController and UIPopoverController (did I miss any?) there is no properly supported way to have multiple view controllers active on the same screen, managing different portions of the view. View controller methods such as presentModalViewController, etc all work on the assumption that there is a single "frontmost" view controller that owns the whole screen, and if you try to have multiple view controllers manage different parts of the view, all kinds of things will break, such as forwarding of screen rotation events and resizing/positioning of views after a page transition.

However if you only need to support iOS 5, the answer is:

Answer number 2 - No problem! Just make sure that all your sub-page-view controllers are correctly hooked up to a master view controller that manages the whole page. That means that in addition to the controllers' views being subviews of a common parent view, the controllers themselves should be child-controllers of a common parent controller. As long as the controller's parentViewController properties are all set correctly, you should be able to manage this kind of composite interface without too much hassle.

Unfortunately, Apple only added public setters for childViewControllers and parentViewControllers in iOS5. In iOS4 and earlier you're limited to Apple's own container controller arrangements and cannot create your own (at least, not without event forwarding issues).

So assuming you need to support iOS4 for now, answer number 3 seems like your best bet: Build your interface using multiple views but a single controller. This isn't too bad though. You can create custom view subclasses that manage heir own subviews (for example there's no rule that says a tableViewDataSource or delegate has to be a UIViewController subclass, or that a button IBAction has to be a method on a view controller instead of another view).

You'll actually find that most of the functionality you normally build into a view controller can be built into a "smart" container view instead, allowing you to split your screen into multiple standalone "controller-views" that manage their own contents.

The only bit that's tricky is doing stuff like transitions between one view and the next. For this you won't be able to use the standard presentModalViewController or pushViewController methods, you'll have to do the animations yourself using CATransitions or UIView animations.

Nick Lockwood
  • 40,865
  • 11
  • 112
  • 103
  • Yes I watched the WWDC video discussing how view controllers can have parent and child view controllers, however as with most WWDC videos they tend to skim over some details here and there. This is helpful though. Is it possible to do this via IB? As hard as I try I cant seem to figure out how to have two VCs in the same screenful via IB, it always creates a new screenful for every VC I drag out. – Adam Eisfeld Jan 26 '12 at 01:36
  • 1
    Ive found this website with some better explanation on the topic: http://www.tumblr.com/tagged/child-view-controller , albeit it explains that you must add the childViewControllers programatically and also position them programmatically. I was hoping there would be an approach to adding and positioning these controllers via IB, if anyone knows. – Adam Eisfeld Jan 26 '12 at 01:48
  • 1
    I don't think you can do it in IB. What you can do is set the size of the root view of your view controller in IB by setting status bar to "none", which will un-disable the width/height controls in the inspector. You can then design the layout for each sub-view in IB, as separate nibs and then just glue the view controllers together in code, which shouldn't be too bad if you only have one or two on-screen. – Nick Lockwood Jan 26 '12 at 01:49
  • Note that the "controller-views" approach I mentioned above not only works on iOS4 but also allows you to composite your views in a single nib file, which is an aded benefit. If you drag a view into IB and set it's class to be your custom "smart" view class, you can then bind other views in the same nib to the outlets and actions defined on your custom view. – Nick Lockwood Jan 26 '12 at 01:52
  • I will do some experiments and reply back either by tonight or tomorrow with my findings. Thanks a lot. – Adam Eisfeld Jan 26 '12 at 01:57
  • 1
    Ive just found this website: http://www.informit.com/articles/article.aspx?p=1760500&seqNum=12 that goes into great detail about how all of this works in iOS5. Its helped me understand a lot more of what I was having trouble with. Certainly helpful. – Adam Eisfeld Jan 26 '12 at 02:03
3

This is definitively possible in IOS 4 :

You have a view controller "A" with its view :

  • Alloc init the view controller "B" you want to had on your view controller "A"
  • Call (void)addSubview:(UIView *)view on the view of the view controller "A" with the view of the view controller "B" as parameter
  • The frame of the view of the view controller "B" is set to fullscreen because of addSubView, so change it to put the view where you want on the view of view controller "A".
  • Add some UIView animations when you change the frame to have a good display.

On IOS5 just use the method on your view controller "A" :

  • (void)addChildViewController:(UIViewController *)childController
BigBrize
  • 31
  • 1
2

The View Controller Programming Guide covers this pretty well.

A view controller manages a set of views. You can have content view controllers and container/navigation view controllers which manage the hierarchy of view controllers (example: navigation view controller can manage a listview controller and a detail controller).

It's covered in more detail here:

http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457

A view controller manages a discrete portion of your application’s user interface. Upon request, it provides a view that can be displayed or interacted with. Often, this view is the root view for a more complex hierarchy of views — buttons, switches, and other user interface elements with existing implementations in iOS. The view controller acts as the central coordinating agent for this view hierarchy, handling exchanges between the views and any relevant controller or data objects.

Multiple view controllers coordinate their efforts to present a single unified user interface.

bryanmac
  • 38,941
  • 11
  • 91
  • 99