Search code examples
objective-cprotocolsdeclared-property

Why do I have to declare a property specified by a protocol in the header, and not the class extension (implementation)


So I have a protocol, which requires a property to be declared:

@protocol MyProtocol <NSObject>
@property MyView *myView;
@end

and an object who conforms to it:

@interface MyViewController : NSViewController <MyProtocol>
@end

However, if I declare the property (specified in the protocol) inside of the implementation file (the class extension):

@interface MyViewController()
@property MyView *myView;
@end

I get this error:

Illegal redeclaration of property in class extension 'MyViewController' (attribute must be 'readwrite', while its primary must be 'readonly')

There appear to be two main SO threads that address this:
attribute must be readwrite while its primary must be read only
and
Can't declare another window

The first answer doesn't explain anything

The second answer says that you can actually circumvent this error by declaring the property inside of the header; and alas

Header

@interface MyViewController : NSViewController <MyProtocol>
@property MyView *myView;
@end

Implementation

@interface MyViewController()
@end

This builds with no errors.

I also know that when you declare a @property inside of a protocol, it doesn't automatically get synthesized.

So if I wanted to keep the @property declaration inside of the implementation, I would have to @synthesize it. And this also works.


So my question is, why does declaring the @property inside of the header vs the implementation file matter if the @property was initially declared inside of a protocol?

Without the protocol, I thought the only difference was making the @property public or private. But clearly there are other things that happen/don't happen if you declare a @property in the header vs the implementation file


Solution

  • Don't declare there property anywhere in your class. It's already declared in the protocol.

    Don't put @property MyView *myView; in either the MyViewController.m or MyViewController.h files.

    To fix the warning about "auto property synthesis", you simply add:

    @synthesize myView = _myView;
    

    to the MyViewController implementation or add explicit getter and setter methods as needed.