Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I provide a default implementation for an Objective-C protocol?

Tags:

I'd like to specify an Objective-C protocol with an optional routine. When the routine is not implemented by a class conforming to the protocol I'd like to use a default implementation in its place. Is there a place in the protocol itself where I can define this default implementation? If not, what is the best practice to reduce copying and pasting this default implementation all over the place?

like image 776
fbrereto Avatar asked Dec 02 '10 00:12

fbrereto


People also ask

Can Objective-C protocols have properties?

You can have properties in a protocol, provided every class that conforms to your protocol have a corresponding @synthesize for that property, or provide a getter and setter. But with a class category you generally can't add instance variables to a class.

What is difference between Objective-C protocol and swift protocol?

In Objective-C, protocols are declared with the “@protocol” keyword. Below is an example of declaring a protocol containing one required method. In Swift, the syntax is a little different but the idea is the same. In Objective-C, you add the protocol name in angle brackets beside the class interface declaration.

What are IOS protocols?

A class interface declares the methods and properties associated with that class. A protocol, by contrast, is used to declare methods and properties that are independent of any specific class. Protocols can include declarations for both instance methods and class methods, as well as properties.


2 Answers

Objective-C protocols have no affordance for default implementations. They are purely collections of method declarations that can be implemented by other classes. The standard practice in Objective-C is to test an object at runtime to see if it responds to the given selector before calling that method on it, using -[NSObject respondsToSelector:]. If e object does not respond to the given selector, the method isn't called.

One way you could achieve the result you're looking for would be to define a method encapsulating the default behavior you're looking for in the calling class, and call that method if the object doesn't pass the test.

Another approach would be to make the method be required in the protocol, and provide default implementations in the superclasses of any classes wherein you may not want to provide a specific implementation.

There are probably other options as well, but generally speaking there isn't a particular standard practice in Objective-C, except perhaps to just not call the given method if it hasn't been implement by the object, per my first paragraph, above.

like image 199
Ryan Avatar answered Oct 15 '22 14:10

Ryan


There is no standard way for doing that as protocols should not define any implementations.

Since Objective-C comes with a neat runtime, you can of course add such a behavior if you really think you need to do it that way (and there's no possibility by achieving the same with inheritance).

Say you declared MyProtocol, then just add an interface with the same name in the .h file under your protocol declaration:

@interface MyProtocol : NSObject <MyProtocol>  + (void)addDefaultImplementationForClass:(Class)conformingClass;  @end 

And create a corresponding implementation file (using MAObjCRuntime for readability here, but the standard runtime functions wouldn't be much more code):

@implementation MyProtocol  + (void)addDefaultImplementationForClass:(Class)conformingClass {   RTProtocol *protocol = [RTProtocol protocolWithName:@"MyProtocol"];   // get all optional instance methods   NSArray *optionalMethods = [protocol methodsRequired:NO instance:YES];   for (RTMethod *method in optionalMethods) {     if (![conformingClass rt_methodForSelector:[method selector]]) {       RTMethod *myMethod = [self rt_methodForSelector:[method selector]];       // add the default implementation from this class       [conformingClass rt_addMethod:myMethod];     }   } }  - (void)someOptionalProtocolMethod {   // default implementation   // will be added to any class that calls addDefault...: on itself } 

Then you just have to call

[MyProtocol addDefaultImplementationForClass:[self class]]; 

in the initializer of your class conforming to the protocol and all default methods will be added.

like image 26
w-m Avatar answered Oct 15 '22 12:10

w-m