3
votes

In the app represented by the image below, I'm currently using three UIViewControllers: One master view controller, one for the main menu, and one for a settings screen which is launched by the main menu. As I'm learning more about how UIViewController works and what it's designed for, I'm questioning the wisdom of my architecture.

It seems to me that the main point of subclassing is to be able to override the methods which get called automatically during the life cycle of the controller: viewDidAppear, viewWillAppear, willRotateToInterfaceOrientation, etc. It appears that these methods are only called if the UIViewController (or subclass) is part of the UIViewController hierarchy. Therefore, there's no point in subclassing UIViewController unless I'm going to use one of the standard means of creating a viewcontroller hierarchy i.e. UINavigationController, [UIViewController presentModalViewController] etc.

I'm wary of using the Cocoa-style means of adding view controllers to the hierarchy because they all seem to be very restrictive. For example, I could display my settings screen using [UIViewController presentModalViewController], but but I don't want it to obscure the entire screen. There's background animation which I want the user to be able to interact with even while the settings screen is visible.

Here are my questions:

1) Is it silly to subclass UIViewController unless I'm going to be adding it to the viewController hierarchy via one of Apple's techniques?

2) Am I correct in my assumption that the built-in means of displaying new views are too restrictive for me, and in order to have the flexibility I want, I'm going to need to just load views via [view addSubview]

3) If it's true that subclassing UIViewController makes no sense for my menu and settings views, how should I avoid having all of my code in one monster UIViewController subclass. Should I just subclass NSObject, add the appropriate IBOutlets and IBActions and pass that in as the File's Owner when I load the nib using [NSBundle loadNibNamed]?

enter image description here

1

1 Answers

5
votes

Good question. First, a point of clarity: What you refer to as "one of Apple's techniques" is referred to in the UIViewController Programming Guide as "indirect presentation", and includes things like modal presentation, being pushed on a navigation stack, presenting a popover controller, etc. Basically all of these view controller methods are considered "indirect" presentation methods, while the use of -addSubview: (something like [someView addSubview:myViewController.view]) is considered "direct" presentation.

From said programming guide: (Giant Block Quote...)

It is recommended that you use only the suggested techniques for displaying the views of your view controllers. In order to present and manage views properly, the system makes a note of each view (and its associated view controller) that you display directly or indirectly. It uses this information later to report view controller-related events to your application. For example, when the device orientation changes, a window uses this information to identify the frontmost view controller and notify it of the change. If you incorporate a view controller’s view into your hierarchy by other means (by adding it as a subview to some other view perhaps), the system assumes you want to manage the view yourself and does not send messages to the associated view controller object. (emphasis mine)

Apart from your setting up your application’s initial interface, most other views are presented indirectly through their view controller objects.

All that is to say that you are correct in thinking that all of those UIViewController messages will be wasted if you if simply add the view to a view hierarchy directly, and take no other further action (key window being the exception). That quote also mentions that it is most common to use indirect presentation.

1) I hesitate to make a blanket statement and say "Yes, in all cases, it is silly to subclass UIViewController unless you're presenting it indirectly." I'm sure there is some good use for it somewhere. I'll settle for saying that I have personally never done so.

2) Absolutely, I would not use a UIViewController subclass here.

3) Allow me to direct your attention to another area of The Programming Guide:

In iPhone applications, the views in a view hierarchy traditionally cover the entire screen... If you want to divide a view hierarchy into multiple subareas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subarea. Then use a single view controller object to manage the generic controller objects.

That pretty clearly syncs up with what you're wanting to do here. You're dead on with your self suggested approach. That "Settings Screen launched by main menu" should be managed by a generic controller object descending from NSObject, which is in turn managed by your full-screen UIViewController subclass.