How do I define a category that adds methods to classes which implement a particular protocol?
Asked Answered
C

4

2

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?

Charleycharlie answered 26/8, 2011 at 20:3 Comment(0)
M
4

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.

Muscarine answered 26/8, 2011 at 21:2 Comment(0)
S
1

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

Defining categories for protocols in Objective-C?

Socialistic answered 26/8, 2011 at 20:16 Comment(0)
C
0

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
Complicated answered 26/8, 2011 at 20:24 Comment(2)
Nope, this is a category on NSManagedObject. It's declaring that NSManagedObject now conforms to the protocol <SOManagedObject>, not that the category applies to NSManagedObject<SOManagedObject>'s.Leong
Wow, I definitely didn't read the question carefully enough. ThanksComplicated
S
0

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.

Shep answered 21/7, 2013 at 6:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.