views:

366

answers:

4

I have a view that contains a UITableView and a UILabel which works perfectly as far as I can tell. I really don't want to manage the UIView and UITableView with the same controller as the UITableViewController handles a lot of housekeeping and according to the documentation:

If the view to be managed is a composite view in which a table view is one of multiple subviews, you must use a custom subclass of UIViewController to manage the table view (and other views). Do not use a UITableViewController object because this controller class sizes the table view to fill the screen between the navigation bar and the tab bar (if either are present).

Why does Apple warn against using it and what will happen if I ignore this warning?

Update: Originally I quoted the following from the Apple Documentation:

You should not use view controllers to manage views that fill only a part of their window—that is, only part of the area defined by the application content rectangle. If you want to have an interface composed of several smaller views, embed them all in a single root view and manage that view with your view controller.

While this issue is probably related to why UITableViewController was designed to be fullscreen, it isn't exactly the same issue.

A: 

In my opinion, The Apple Way is to provide you the "one" solution. This served the end-users very well. No choice, no headache.

We are programmers and we want to and need to customize. However, in some cases, Apple still doesn't want us to do too many changes. For example, the height of tab bar, tool bar and nav bar, some default sizes of the UI components(table view), some default behaviors, etc.. And when designing a framework and a suite of APIs, they need to nail down some decisions. Even if it's a very good and flexible design, there is always one programmer in the world wants to do something different and find it difficult to achieve against the design.

In short, you want a table view and a label on the same screen, but they don't think so. :)

yehnan
+5  A: 

The major practical reason to use only one view controller per screen is because that is the only way to manage navigation.

For example, suppose you have screen that has two separate view controllers and you load it with the navigation controller. Which of the two view controllers do you push and how do you load and reference the second one? (Not to mention the overhead of coordinating the two separate controllers simultaneously.)

I don't think using a single custom controller is a big of a hassle as you think.

Remember, there is no need for the TableviewDataSource and the TableViewDelegate to be in the actual controller. The Apple templates just do that for convenience. You can put the methods implementing both protocol in one class or separate them each into there own class. Then you simply link them up with the table in your custom controller. That way, all the custom controller has to do is manage the frame of tableview itself. All the configuration and data management will be in separate and self-contained objects. The custom control can easily message them if you need data from the other UI elements.

This kind of flexibility, customization and encapsulation is why the delegate design pattern is used in the first place. You can customize the heck out of anything without having to create one monster class that does everything. Instead, you just pop in a delegate module and go.

Edit01: Response to comment

If I understand your layout correctly, your problem is that the UITableViewController is hardwired to set the table to fill the available view. Most of the time the tableview is the top view itself and that works. The main function of the UITableViewController is to position the table so if you're using a non-standard layout, you don't need it. You can just use a generic view controller and let the nib set the table's frame (or do it programmatically). Like I said, its easy to think that the delegate and datasource methods have to be in the controller but they don't. You should just get rid of the tableViewController all together because it serves no purpose in your particular design.

TechZen
The UIView contains the UITableView so the UIView is loaded by the navigation controller and the Table is a part of the view and it has connections to a my TableViewController in the xib file.
Casebash
See Edit01 in the body of the answer above.
TechZen
"If I understand your layout correctly, your problem is that the UITableViewController is hardwired to set the table to fill the available view" - that would be a problem if I were to try to use a UITableView to control the UIView as well. However, with my current setup, everything is working fine as is. I was just curious about the warning.
Casebash
Well, then I think the answer is as I explained. The logical view hierarchy is maintained by the view controllers. Having multiple, especially logically equal controllers, for one display disrupts the hierarchy. Further, there is no practical reason to do so because the one controller per screen will work for all circumstances.
TechZen
In the world of the iPad, this warning is just not true. Apple's own `UISplitViewController` gives the lie to this warning, for example. The way I read the warning is a little more subtle; it basically says: don't write custom `UIViewController` subclasses that nest other view controllers. That's because it is entirely undocumented how hierarchies of view controllers should behave. What messages should be passed between them? Sure, Apple can (and does) do it, but you shouldn't. Build your own controller class hierarchy if necessary (it often is!)
Dave Peck
No, you have to nest controllers and the behavior is well documented. The trick is that you have to have a well defined hierarchy with one single top most controller. This is how the navigation, tabbar and splitivew controllers work. One controller must have final responsibility for the entire visible screen. If you try to set up two equal controllers, the system breaks down.
TechZen
It is seldom necessary to have multiple controllers for a single view static view no matter how complex it might be. By using the delegate pattern, you don't have to cram all the functionality for the UI elements into a single controller. You can have a controller that manages the basic layout and then various delegate objects to manage the individual UI elements.
TechZen
+2  A: 

To me, the important detail in Apple's documentation is that they advise you not to use "view controllers [i.e., instances of UIViewController or its subclasses] to manage views that fill only a part of their window". There is nothing wrong with using several (custom) controllers for non-fullscreen views, they just should not be UIViewController objects.

UIViewController expects that its view takes up the entire screen and if it doesn't, you might get strange results. The view controller resizes the view to fit the window (minus navigation bars and toolbars) when it appears, it manages device orientation (which is hard to apply correctly if its view does not take up the entire screen) etc. So given how UIViewController works, I think there is merit to Apple's advice.

However, that doesn't mean that you can't write your own controller classes to manage your subviews. Besides the things I mentioned above, interacting with tab bar and navigation controllers, and receiving memory warnings, there isn't really much that UIViewController does. You could just write your custom controller class (subclassed from NSObject), instantiate it in your "normal" fullscreen view controller and let it handle the interaction with your view.

The only problem I see is the responder chain. A view controller is part of the responder chain so that touch events that your views don't handle get forwarded to the view controller. As I see it, there is no easy way to place your custom controller in the responder chain. I don't know if this is relevant for you. If you can manage interaction with your view with the target-action mechanism, it wouldn't matter.

Ole Begemann
+1  A: 

I have an application where I did use 2 separate UIViewController subclasses below another view controller to manage a table view and a toolbar. It 'kind of' works, but I got myself into a massive pickle as a result and now realize that I should not be using UIViewController subclasses for the sub controllers because they contain behavior that I don't need and that gets in the way.

The sort of things that went wrong, tended to be:

  • Strange resizing of the views when coming back from sub navigation and geometry calculations being different between viewWillLoad and viewDidLoad etc.

  • Difficulty in handling low memory warnings when I freed the subview controllers when I shouldn't have done.

Its the expectation that UIViewController subclasses won't be used like this, and the way they handle events, using the navigation controller etc that made trying to use more than one UIViewController subclass for the same page tricky because you end up spending more time circumventing their behaviour in this context.

Johnno