14

I have a protocol named MyProtocol. MyProtocol has an required method:

- (NSUInteger)length;

And some other methods.

Now i want to make the NSString class conform to MyProtocol with a category. Like so:

@interface NSString (NSStringWithMyProtocol) <MyProtocol>
@end

In this category i implement all methods excluding the 'length' method, because i want the original NSString implementation. I do not want to override it in this particular class.

Now i get a warning because of an incomplete implementation of MyProtocol in the category.

I know there are a few solutions to solve this.

  1. Make the method optional
  2. Pointer Swizzling
  3. Adding subclass to class which is conform to the protocol. Then leave out the implementation.

I do not want to use these options because they result in a bad design for the rest of my code.
Option 3 is bad, because of existing direct subclasses will not be conform to the protocol.

Does anybody know how to remove the warning without implementing the length method?

NOTE: The class, category and protocol are just examples. I did encounter this problem with other classes which i could not post about. Thanks

EDIT: Added the third option.

Full Code:

The protocol:

@protocol MyProtocol <NSObject>

- (void) myMethod;
- (NSInteger) length;

@end

The category header:

#import <Foundation/Foundation.h>
#import "MyProtocol.h"

@interface NSString (MyProtocol) <MyProtocol>
@end

The category implementation:

@implementation NSString (MyProtocol)

- (void)myMethod {

}

@end

This results in the following warnings.

Incomplete implementation

Method in protocol not implemented

In this screenshot you can see my warning: Screen shot

I tried compiling with LLVM GCC 4.2 and the Apple LLVM 3.0 compiler. I also compiled on xcode 4.0.2 and Xcode 4.2. I'm on OS X 10.6.8.

Mats Stijlaart
  • 5,058
  • 7
  • 42
  • 58

2 Answers2

13

I cannot reproduce this issue. Can you post code that demonstrates it? The following compiles without warnings on 10.7.

#import <Foundation/Foundation.h>

@protocol MyProtocol <NSObject>
- (NSUInteger)length;
@end

@interface NSString (NSStringWithMyProtocol) <MyProtocol>
@end

int main (int argc, const char * argv[]) {
  @autoreleasepool {
    id<MyProtocol> foo = @"foo";
    NSLog(@"%@", foo);    
  }
  return 0;
}
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • 2
    I added my code. I also see whats different. You did not define an implementation for the category. – Mats Stijlaart Sep 02 '11 at 08:15
  • 1
    Clang apparently is much stricter about this than gcc. In the vast majority of cases, that's a good thing, but in this case I believe you've pushed it to the edge of the current implementation. I would open a defect against clang. – Rob Napier Sep 02 '11 at 13:46
  • 1
    I think i will sign this as the correct answer. Note that it will only function when a class already did implement all methods defined in the protocol. The categories implementation can not exist with a partial implementation of the protocol. – Mats Stijlaart Sep 04 '11 at 00:44
  • This question and answer were helpful to me. I get the same warning, but my code still compiles and runs FWIW. – carbocation May 27 '14 at 22:53
0

You might consider this a bit of a hack, and I don't know if it will even work, but how about declaring it as a read only property

@property (readonly, assign) NSUInteger length;

and then in the implementation of your category, make it @dynamic

JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • 1
    Whould work for a getter, but not for the setter. Didn't indicate this was just an example. Wasn't able to talk about my production code. – Mats Stijlaart Aug 31 '11 at 12:04
  • 1
    True. But that will not only resolve setter/getter kind of methods. As noted in my previous comment, i deal with other classes and methods. – Mats Stijlaart Aug 31 '11 at 12:07