I have a UITableViewController subclass that's instantiated, depending on where it's used, in a NIB or via code. In both cases I want to do customization in the initializer method. Does that mean I need to implement both initWithNibName:bundle: and initWithCoder:, and would each method call its respective super initializer?
While I don't need this right now, what if I also want to be able to instantiate the view controller with initWithStyle:? Would I then need 3 different init methods that replicate the same behavior?
It seems like this violates the whole designated initializer convention, as there would essentially be 3 separate initializers that don't end up calling a common init method. Or is there a way to create a common designated initializer while supporting the 3 different instantiate routes?
-
Implement:
- (void) viewDidLoadand do your component initialization there.
It has the advantage of only doing the initialization when the view is actually requested.
Or just make a separate setup method invoked by all initializers.
Daniel Dickison : I can't use viewDidLoad because, specifically, I need to set up self.navigationItem which may be used before the view is loaded. I could make a separate setup method. So is it just that NSCoding is fundamentally an exception to the "single designated initializer" rule? -
My confusion was based on the mistaken belief that each class should have a single designated initializer. This is not true, and in the case of
UITableViewControllerthere are 3 designated initializers (as far as I can tell):initWithStyle:declared locallyinitWithNibName:bundle:inherited fromUIViewControllerinitWithCoder:from adoptingNSCodingprotocol
You need to override 1 or more of these in your subclass depending on how your subclass gets instantiated. In my case I had to implement #2 and #3 since the class can be loaded from a NIB, or instantiated via code with reference to a NIB. (I imagine it's rare that you'll use both
initWithStyle:andinitWithNibName:bundle:for a single class.)I found Apple's Coding Guidelines for Cocoa helpful.
-
To clarify,
initWithStyle:, beingUITableViewController's only published initializer in the docs, is its one explicit designated initializer.initWithNibName:bundle:is inherited from UIViewController and is the designated initializer for that class. As such, in accordance with Cocoa guidelines,UITableViewControllermust override this method (by implementing it). However, this does not make it a designated initializer ofUITableViewController.initWithCoder:is, as you point out, an implicit designated initializer fromNSCoding. -
Internally,
- UITableViewController's
-initWithStyle:calls the super's-initthen set the_tableViewStyleivar. - UIViewController's
-initsimply calls-initWithNibName:bundle:with default arguments. - UITableViewController does not override
-initWithNibName:bundle:.
Therefore, if you override
-initWithNibName:bundle:then-initWithStyle:will adopt the change too. Of course, to play safe (as you shouldn't rely on implementation details), override both of them.(And no need to override
-initWithCoder:unless you will un/archive the instances.) - UITableViewController's
0 comments:
Post a Comment