1

Hey guys, I have a protocol which defines a number of ObjC-2.0 properties, like so:

@protocol Repeatable <NSCoding>
@required
@property (nonatomic, retain) Date *startDate;
@property (nonatomic, retain) Date *endDate;
@end

I have another class that implements the protocol:

@interface AbstractRepeatable : NSObject <Repeatable>

And finally, in AbstractRepeatable, I am implementing a method defined by the protocol:

- (BOOL)isEqualToRepeatable:(Repeatable *)r {
    if (r.startDate != startDate) // Compiler error here
        return NO;
    return YES;
}

Bits and pieces have been excluded for example-sake, but when compiling, I receive the familiar "request for member 'startDate' in something not a structure or union" on the line noted above. The AbstractRepeatable obviously includes the Repeatable header, otherwise the protocol would not be visible, so I don't know which part I'm missing.

Craig Otis
  • 31,257
  • 32
  • 136
  • 234
  • 1
    This answer might clear some things up for you: http://stackoverflow.com/questions/844678/how-to-handle-objective-c-protocols-that-contain-properties/844785#844785 – NSSec Sep 30 '09 at 14:34
  • I'm synthesizing the property in AbstractRepeatable, I can't figure out why the prop isn't recognized. – Craig Otis Sep 30 '09 at 15:29

3 Answers3

7

In your isEqualToRepeatable: method you are treating Repeatable as a class, not a protocol. Try using the following. Everything should work fine after that. I tested it. (Fingers crossed that I won't look stupid.)

- (BOOL)isEqualToRepeatable:(id<Repeatable>)r {
    if (r.startDate != startDate) // Compiler error here
        return NO;
    return YES;
}
Cory Kilger
  • 13,034
  • 3
  • 33
  • 24
  • I'd be surprised that entirely fixes the issue. There is a serious bug in the existing compilers with @property() in protocols. – bbum Sep 30 '09 at 19:56
1

That should work and do what you expect. But it doesn't because the compiler is broken.

Sorry about that.

As a workaround, you'll need to declare the methods in your protocol:

@protocol Repeatable <NSCoding>
@required
@property (nonatomic, retain) Date *startDate;
- (Date *) startDate;
- (void) setStartDate: (Date *) aDate;

@property (nonatomic, retain) Date *endDate;
- (Date *) endDate;
- (void) setEndDate: (Date *) aDate;
@end

Skipping the @property, if you want. Once the compiler is fixed, the above still won't generate any warnings.

(Yes, you still can @synthesize the methods. I believe that @synthesize will work in this case. If it doesn't -- which it might not -- then you'll need to redeclare the properties in the class -- potentially in a class extension -- until the compiler is fixed. If this second issue proves to be the case, please file a bug via http://bugreport.apple.com/)

bbum
  • 162,346
  • 23
  • 271
  • 359
  • 1
    I believe the compiler is synthesizing the getters/setters. See the chosen answer for a good explanation. – Craig Otis Sep 30 '09 at 16:52
  • The compiler is synthesizing the getter/setters. That isn't the problem. The problem is that the compiler does not see @property() in class declarations as indicating that methods are required correctly. In some cases, it'll lead to incorrect code gen. – bbum Sep 30 '09 at 19:56
0

@property ... startDate only declares two methods -startDate and -setStartDate:.

You have to actually implement them. In a protocol, this cannot be done with instance variables.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
  • Defining the properties in the protocol just ensures that the subclasses (or implementers, more specifically) synthesize the properties, and that you can pass in any Repeatable to a method, and have code that acts on those properties, assuming they exist in the actual object, which is an implementation of that protocol. – Craig Otis Sep 30 '09 at 15:34
  • I should clarify - Defining the properties in the protocol does not synthesize the variables. Any implementation of the protocol *must* synthesize (or provide dynamic accessor methods) to ensure that the property is "maintained." – Craig Otis Sep 30 '09 at 15:36
  • This is a good point. Have you tried to replace (r.startDate != startDate) by (r.startDate != [self startDate]) ? – mouviciel Sep 30 '09 at 15:42
  • The compiler error was on the r.startDate 'getter', not the startDate instance var. Answer chosen above. :) – Craig Otis Sep 30 '09 at 16:57
  • In XCode 4.4, we got the following change: "Objective-C @properties are synthesized by default when not explicitly implemented." – Victor Zamanian Apr 23 '13 at 15:49