agent.smith
agent.smith

Reputation: 9416

Objective C: Declaring a selector but implementing it in objects category

I have a framework in obj-c which is included by other modules. I want to allow the modules which are going to include it to provide their own implementation for certain methods.

I can't use subclassing because of some issues around serializing these objects. So, have to rely on using category.

I am thinking of declaring a method/selector for the object and then modules will define the category and implement that method. Something like below:

Framework will declare interface like below: 
@interface framework:NSObject
- (void)methodToBeImplemented;
@end

@implementation framework()
- (void)invokeClientDefinedMethod
{
   if([self respondsToSelector:@(methodToBeImplemented)]) {
      [self methodToBeImplemented];
   }
}

//Module-1 will link against this framework and define the category
@implementation framework(methodImplementor)
- (void)methodToBeImplemented 
{
   ...
}
@end

Can I choose not to implement methodToBeImplemented at all in framework and implementation to be provided by the modules themselves. I know that I can do it performSelector route. But I cringe to do so because I want to send pointers to my method which is not really possible with performSelector

Upvotes: 1

Views: 50

Answers (1)

Rob Napier
Rob Napier

Reputation: 299265

If possible, I would highly recommend using a delegate pattern for your object so that callers can pass a delegate that conforms to a protocol rather than directly extending the class. That's the normal way to implement this kind of system. But if there's a particular reason a delegate is not possible, you can build what you're describing.

What you're looking for is an informal protocol, which is how almost all protocols were handled prior to the introduction of @optional.

What you want to do is define a category on your class in your public header:

@interface Framework (OverridePoints)
- (void)methodToBeImplemented
@end

This declares that such a method may exist, but it does not enforce its actually being implemented. The key is having a name in the parentheses. This can be anything (I used "OverridePoints" here), but it cannot be empty since that would be an extension instead of a category.

Once you have that, then the rest of your ideas work. You can test for respondsToSelector:, and the consumer can implement (or not implement) the category methods just as you describe.

The one danger is that there is nothing preventing multiple parts of the program implementing the same method in categories. That is undefined behavior, but the compiler will not catch it for you.

Upvotes: 3

Related Questions