Why doesn't Apple allow subclassing of UINavigationController? And what are my alternatives to subclassing?
I'm currently building a tabbed iPhone application where each tab's view controller is an instance of UINavigationController
, and where every subcontroller of every one of the UINavigationController
instances is an instance of UITableViewController
. Ideally, I'd like to subclass UINavigationController
so that the controller for each tab is a subclass of UINavigationController that (in addition to having all the standard UINavigationController
functionality, obviously) serves as the datasource and the delegate for each of the table views associated with its subcontrollers. Trying to do this seems to break the basic UINavigationController
functionality in the subclass.
Seeing as Apple says in their iPhone documentation that one shouldn't subclass UINavigationController
, and thin开发者_StackOverflow中文版gs seem to break when one does, I'm wondering how I should go about extending UINavigationController's
functionality without subclassing, and generally speaking, how one should work around subclassing limitations when doing Cocoa development.
Thanks!
Why on earth do you want the UINavigationController
to act as a datasource for the table? The whole point of UITableViewController
is that you subclass it, and it acts as the datasource for the UITableView
that it also places in, and fills, the parent view.
For reference, note that since iOS 6, UINavigationController can be subclassed legally.
This class is generally used as-is but may be subclassed in iOS 6 and later. UINavigationController Class Reference
Of course, that doesn't mean you always should. But you can.
I'm going to go ahead and say your idea has some merit, if at every level you are truly using the same kind of data and each level perhaps has a different delegate to handle cell creation.
Basically there's no reason you cannot subclass UINavigation controller to add a totally orthogonal layer of data atop it, because it has nothing to do with the UI or behavior that UINavigationController is managing (which is what Apple is concerned you will be messing with). To those opposed to the idea, think of it as a per-tab data store that all pages in a tab can access instead of every page in the system having to go to the AppDelegate, or have a bunch of singletons. Well basically it's a singleton, but at least one that is already there and gets the reference passed around automatically.
All that said, I'll end with an alternate design proposal - I think what you are probably wanting to do is drill down through multiple layers reusing the same code to generate cells and such because you have the same kinds of data at each layer. A better approach to handle that is to have one view controller that you feed the subset of data to display, and when a user drills down it simply creates another instance of the same view controller with that new subset of data. That approach is much better than the idea of having the navigation controller act as a table delegate for each level, because you'd have to do a ton of rewiring moving back and forth and it would require even more work to remember scroll position at each level to boot. That's why you want to keep drill-downs using multiple instances of view controllers, but multiple instances doesn't have to mean multiple classes.
As I understand it, subclassing is not encouraged because Objective C allows a subclass too much access to the internal workings of its superclass.
The suggested alternative to writing a subclass is to write a delegate, in this case a UINavigationControllerDelegate. You can then encapsulate the specific behavior you want to extend into this delegate class, and link it up to the UINavigationController whenever you need it.
If the available controller heirarchy does not serve your needs in terms of handling data (my assumption, since we don't know why you want one object to be the datasource for multiple views), you can always create additional data and/or controller classes (subclasses of NSObject at least).
You can have a data or other object persist while changing views in various ways. (1) a property of your application delegate class. Any object in your app can get your app delegate instance with
[[UIApplication sharedApplication] delegate]
Use this sparingly since it's essentially creating globals.
(2) You can pass data or other objects from controller to controller as you push view controller subclasses or bring them up within tabs.
(3) Core Data is another way but requires a lot of Cocoa under your belt, and you still have to manage the context instance(s).
Because they want to avoid the UI inconsistency that plagues every other platform.
精彩评论