7

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

Community
  • 1
  • 1
A O
  • 5,516
  • 3
  • 33
  • 68
  • 1
    Since you publicly declare that your class conforms to the protocol (in the .h file), you must also publicly declare that you have the property. If you only want the property to be private, conform to the protocol on the class extension instead of the public interface. – rmaddy Sep 28 '15 at 15:05
  • I still get that error :\ and also I don't think I can do that anyways because my other objects need to know that `MyViewController` conforms to `MyProtocol`-- and it looks like nobody knows it does if I conform in the class extension – A O Sep 28 '15 at 15:22
  • OK, then if you need to publicly declare the protocol, then why wouldn't you publicly declare the property? – rmaddy Sep 28 '15 at 15:23
  • Yeah I should be, but I guess I just don't understand why it matters if I declare the `@property` inside of the header or the implementation, and why if I declare the `@property` as `readwrite` in the protocol, but as `readonly` in the implementation-- it works – A O Sep 28 '15 at 15:26
  • It needs to be public, so it must be declared in the interface (header), not the implementation. – rmaddy Sep 28 '15 at 15:27
  • Sorry I'm being annoying; but I don't think it must be declared in the header? It seems to only be an issue with `@property`. I have methods declared in my protocol, and the compiler is totally fine with me implementing them without declaring them in the header. Also I don't get why it magically works when I add the `readwrite` and `readonly` properties – A O Sep 28 '15 at 15:30

1 Answers1

6

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.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • So I'm assuming then by declaring the property as `readwrite` in the protocol and `readonly` in the implementation, the compiler just assumes to synthesize the property automatically for some reason? – A O Sep 28 '15 at 17:12
  • 1
    Under Xcode 7 you can't declare the property as read-only (or readwrite) in the class extension. – rmaddy Sep 28 '15 at 17:15