views:

1663

answers:

3

I've seen usage of Objective-C protocols get used in a fashion such as the following:

@protocol MyProtocol <NSObject>

@required

@property (readonly) NSString *title;

@optional

- (void) someMethod;

@end

I've seen this format used instead of writing a concrete superclass that subclasses extend. The question is, if you conform to this protocol, do you need to synthesize the properties yourself? If you're extending a superclass, the answer is obviously no, you do not need to. But how does one deal with properties that a protocol requires to conform to?

To my understanding, you still need to declare the instance variables in the header file of an object that conforms to a protocol that requires these properties. In that case, can we assume that they're just a guiding principle? CLearly the same isn't the case for a required method. The compiler will slap your wrist for excluding a required method that a protocol lists. What's the story behind properties though?

Here's an example that generates a compile error (Note: I've trimmed the code which doesn't reflect upon the problem at hand):

MyProtocol.h

@protocol MyProtocol <NSObject>

@required
@property (nonatomic, retain) id anObject;

@optional

TestProtocolsViewController.h

- (void)iDoCoolStuff;

@end

#import <MyProtocol.h>

@interface TestProtocolsViewController : UIViewController <MyProtocol> {

}

@end

TestProtocolsViewController.m

#import "TestProtocolsViewController.h"

@implementation TestProtocolsViewController
@synthesize anObject; // anObject doesn't exist, even though we conform to MyProtocol.

- (void)dealloc {
    [anObject release]; //anObject doesn't exist, even though we conform to MyProtocol.
    [super dealloc];
}

@end
A: 

all you have to do really is to drop a

@synthesize title;

in your implementation and you should be all set. it works the same way as just putting the property in your class interface.

Kevlar
Are you completely sure? I have an optional property set in a protocol, and when I only @synthesize it in a concrete class that conforms to that protocol -- I get a compiler error claiming it's an undeclared variable. No typos confirmed.
Coocoo4Cocoa
i'm not sure about optional properties, but one thing i forgot to mention like mralex said is that you need to tie it to a member variable, either by naming that variable title, or saying @synthesize title = myinstancevar;
Kevlar
A: 

The variable, anObject, needs to be defined in your TestProtocolsViewController class definition, the protocol is just informing you that it should be there.

The compiler errors are telling you the truth - the variable doesn't exist. @properties are just helpers after all.

mralex
+4  A: 

The protocol is just telling everyone that knows about your class through the protocol, that the property anObject will be there. Protocols are not real, they have no variables or methods themselves - they only describe a specfic set of attributes that is true about your class so that objects holding references to them can use them in specific ways.

That means in your class that conforms to your protocol, you have to do everything to make sure anObject works.

@property and @synthesize are at heart two mechanisms that generate code for you. @property is just saying there will be a getter (and/or setter) method for that property name. If you don't synthesize you need to do something to make sure that the property method(s) you claimed in the header would be there actually exists - the simplest way is to of course have a local variable and an @synthesize directive. But you have to have something.

Kendall Helmstetter Gelner