How do I define a category that adds methods to cl

2019-05-21 02:18发布

问题:

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 doesn't seem to be valid. How do I define a category that adds methods to classes which implement a particular protocol?

回答1:

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.



回答2:

I don't think it is possible. A similar question to this was answered earlier:

Defining categories for protocols in Objective-C?



回答3:

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


回答4:

Adam Sharp posted a solution that worked for me.

It involves 3 steps:

  1. Defining the methods you want to add as @optional on a protocol.
  2. Making the objects you want to extend conform to that protocol.
  3. Copying those methods into those objects at runtime.

Check out the link for the full details.