4

I have kind of an abstract class for my UIViewControllers (lets call it MyViewController) which overrides some basic methods like viewDidLoad or viewDidDisappear. In this methods some preparations are made, like setting up colors for the navigation bar, or preparing the bar buttons or something like that.

Now I want this basic behaviour for my UITableViewControllers also. So I made a new class that inherits UITableViewController (lets call it MyTableViewController) and copied 99% of the code from MyViewController.

UML diagram of the current situation

In this image you see my current architecture. Listed are the overriden methods, in which other private methods are called. Again, MyViewController and MyTableViewController share 99% codebase (only difference is the name of the class and the super class).

For obvious reasons this is crap.

Is there an elegant solution to make MyTableViewController a subclass of both MyViewController and UITableViewController?

2 Answers 2

4

This is one suggestion, but I don't know how useful it is because I don't know your code.

You could implement a bunch of methods in a category for the UIViewcontroller class. For example:

@implementation UIViewController (myCategory)
- (void)setupColors;
...
@end

Since both MyViewcontroller and MyTableViewcontroller inherit from UIViewController, they would inherit your methods.

The only thing that you would copy in both implementation is the invocation of those functions, but the duplicate code would be much less.

- viewDidLoad...
{
     [self setupColors];
}

Just be careful if you override methods, because you can't call [super ... ] on a category as you can in an inherited class

Sign up to request clarification or add additional context in comments.

7 Comments

Well for few classes this might work. But I would have to copy/paste 50 lines per subclass. As soon as I have more than 5 subclasses There will be more code to copy with this solution.
50 lines is not that much. Anyway, you'll realize that with any other alternative (a few of them in my mind) you'll still need to duplicate some code.
50 lines * n subclasses = huge number imo. But thx for your effor so far.
@MarcMosby If you use a strategy pattern like what's suggested here, you should only need to add those lines to a few of the key methods and then just always subclass those. I can't think of many other view controllers that you'd subclass aside from UITableViewController, UIViewController and maybe UICollectionViewController. You could have your personal base class version of each of those that calls your strategy methods for things like viewDidAppear or rotation or whatever.
I wasn't getting it at first, but your solution makes perfect sense now. Thanks @JasonCoco and Merlevede.
|
1

Shared implementation for your common methods could be done either with a category or with composition. Since a category can't be used to directly override existing interface (e.g. viewDidLoad:) you would need to put your private methods into the category and call them from your subclass overrides. Another option would be to put your shared implementation in a separate class (which might be a singleton) and compose an instance of that as a property of both MyViewController and MyTableViewController, e.g.:

@interface MyViewController : UIViewController
@property (nonatomic, strong) MyControllerStyler *controllerStyler;
@end

@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [controllerStyler viewDidLoad];
}
...etc...

The composed class's methods could reference the controller if needed, e.g.:

@interface MyControllerStyler : NSObject

- (void)viewDidLoadInController: (UIViewController *)controller;
...etc...

While a category seems perfectly fine for this example, if your extensions collectively represent a meaningful unit of your design (such as a collection of visual styling attributes) that might argue for a separate object (or objects) to better represent your intent.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.