views:

585

answers:

2

I have the following code protocol snippets:

@protocol FooDelegate;

@interface Foo : UIViewController { id delegate; } ...

@protocol FooDelegate ... // method 1 ... // method 2 ... @end

Also, the following code which implements FooDelegate:

@interface Bar1 : UIViewController { ... }

@interface Bar2 : UITableViewController { ... }

It turns out the implementation of FooDelegate is the same on both Bar1 and Bar2 classes. I currently just copy FooDelegate implementation code from Bar1 to Bar2.

How do I structure/implement in such a way that Bar1 and Bar2 share the same code in a single code base (not as currently with 2 copies) since they are the same?

Thanks in advance for your help.

A: 

Make a new object, MyFooDelegate:

@interface MyFooDelegate : NSObject <FooDelegate>

Then Bar1 and Bar2 can each create an instance of it (or share one instance). In those classes you can eliminate the delegate methods and add lines like:

MyFooDelegate *myDooDelegateInstance = ...;

foo.delegate = myFooDelegateInstance;

You could also create an instance of MyFooDelegate in a NIB file and connect the view controller's delegate outlets to it, if desired.

That way, you won't have any duplicated code in your source files or in your executables.

benzado
I don't think that really solves the problem a whole lot. Both Bar1 and Bar2 still need to add in code in all the same places to hook up to their MyFooDelegate instance. The real solution would be a form of mixins, which Cocoa doesn't really have in this case.
Shaggy Frog
If the problem is having the same code in two source files, it absolutely solves the problem.
benzado
No, it exchanges one problem for another. Because now you just have a different kind of source code that is the same in two source files.
Shaggy Frog
Wait, so you're saying that factoring repeated code into a function is never a solution since the function call (a different kind of source code) will still be repeated code?
benzado
It depends on how Bar1 and Bar2 will be using this new "MyFooDelegate". If they have to change their behaviour based on what the delegate does, then yes, you end up with repeated code.
Shaggy Frog
Since pion says they are the exact same code, I find that unlikely. If the new object needs to send a message to its "owner" object, that's not a big deal.I think I've provided a good enough solution without requiring changes to the language specification, app frameworks, or laws of physics. Every solution is suboptimal if you pick at it enough.
benzado
A: 

Option A: Implement the method in a Category

Any properties used must be declared in UIViewController.

UITableViewController is a subclass of UIViewController.

//UIViewController+MyAdditions.h
@interface UIViewController (MyAdditions)
- (void)myCommonMethod;
@end

//UIViewController+MyAdditions.m

@implementation UIViewController (MyAddtions)
- (void)myCommonMethod {
// insert code here
}

The new method added to UIViewController will be inherited by Bar1 and Bar2

Option B: Create a MyViewControllerHelper class

If you can, implement your common code as a class method, otherwise you will need to create an instance of your helper class either temporarily or as a property of Bar1 and Bar2

@interface MyViewControllerHelper : NSObject
- (void)myCommonMethod;
@end

@implementation MyViewControllerHelper
- (void)myCommonMethod {
    // common code here
}

@interface Bar1 : UIViewController {
MyViewControllerHelper *helper;
}
@property MyViewControllerHelper *helper;
@end

@implementation Bar1
@synthesize helper;
- (void)someMethod {
    [helper myCommonMethod];
}
@end

@interface Bar2 : UITableViewController {
MyViewControllerHelper *helper;
}
@property MyViewControllerHelper;
@end

@implementation Bar2
@synthesize helper;
- (void)someOtherMethod {
    [helper myCommonMethod];
}
@end
falconcreek
Option A has some unnecessary risk, since you'll be adding delegate methods to the system UIViewController class. If the delegate protocol is entirely a custom one, it's probably safe, but if it's a system-provided protocol (e.g., UIActionSheetDelegate), you could theoretically break unrelated stuff (e.g., the system photo picker view controller).
benzado
It's always about choice. Option A avoids delegation entirely which I thought might cause problems because UIViewController does not implement a delegate protocol but UITableViewController does. Foo and Bar examples don't provide enough context to determine whether they are useful utility methods that are *missing* from the API (think base64 encoding of strings). Any risk has to be weighed against violating the *dry* principle and the complexity of managing a category or coupling between a controller and new helper objects.
falconcreek