How do I define a category that adds methods to classes which implement a particular protocol?
I want to add some methods to subclasses of NSManagedObject that implement the SOManagedObject protocol. I've tried defining it like this:
@interface NSManagedObject <SOManagedObject> (MyExtensionMethods)
...
@end
...but that does开发者_开发问答n't seem to be valid. How do I define a category that adds methods to classes which implement a particular protocol?
Defining such a category on all such classes in general is not easily solvable. But your actual problem seems simpler: How does one add a category method to NSManagedObject
for use only with subclasses that implement <SOManagedObject>
? This is solvable.
What you want to do is add the method to NSManagedObject
, then check that the instance you're working with can handle the messages you want to send it from <SOManagedObject>
.
Let us suppose that we are given:
/* SOManagedObject.h */
@protocol SOManagedObject
- (void)frobble_so;
- (void)bobble_so;
@end
Now let's add a category method to all NSManagedObject
subclasses that implement SOManagedObject
:
/* NSManagedObject+SOConvenience.h */
@interface NSManagedObject (SOConvience)
/* Frobbles and bobbles - no effect on non-<SOManagedObject>-conforming
* instances. */
- (void)frobbleAndBobble_so;
@end
To do so, we implement the method like so:
/* NSManagedObject+SOConvenience.m */
@implementation NSManagedObject (SOConvenience)
- (void)frobbleAndBobble_so
{
if (![self conformsToProtocol:@protocol(SOManagedObject)]) return;
NSLog(@"%s: Thunderbirds are GO! Let's frobble and bobble!", __func__);
[self frobble_so];
[self bobble_so];
}
@end
You could optionally assert to ensure you are not sending the method to the wrong objects, or you could use respondsToSelector:
instead of checking for protocol conformance. Whatever floats your boat, but this general tack should take you where you want to go.
I don't think it is possible. A similar question to this was answered earlier:
Defining categories for protocols in Objective-C?
Edit: I misread the question; I don't think it's possible to do what you're trying to do without messing with the Objective-C runtime. See Dave's comment below for why my answer is incorrect.
You should be able to do this if you swap the protocol and category notation like so:
@interface NSManagedObject (MyExtensionMethods) <SOManagedObject>
...
@end
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
- Defining the methods you want to add as
@optional
on a protocol. - Making the objects you want to extend conform to that protocol.
- Copying those methods into those objects at runtime.
Check out the link for the full details.
精彩评论