26

Prior to ARC, if I wanted a property to be readonly to using it but have it writeable within the class, I could do:

// Public declaration
@interface SomeClass : NSObject
    @property (nonatomic, retain, readonly) NSString *myProperty;
@end

// private interface declaration
@interface SomeClass()
- (void)setMyProperty:(NSString *)newValue;
@end

@implementation SomeClass

- (void)setMyProperty:(NSString *)newValue
{ 
   if (myProperty != newValue) {
      [myProperty release];
      myProperty = [newValue retain];
   }
}
- (void)doSomethingPrivate
{
    [self setMyProperty:@"some value that only this class can set"];
}
@end

With ARC, if I wanted to override setMyProperty, you can't use retain/release keywords anymore so is this adequate and correct?

// interface declaration:
@property (nonatomic, strong, readonly) NSString *myProperty;

// Setter override
- (void)setMyProperty:(NSString *)newValue
{ 
   if (myProperty != newValue) {
      myProperty = newValue;
   }
}
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Jonas Gardner
  • 2,458
  • 5
  • 22
  • 28

2 Answers2

62

Yes, that is adequate, but you don't even need that much.

You can do

- (void)setMyProperty:(NSString *)newValue
{ 
      myProperty = newValue;
}

The compiler will do the right thing here.

The other thing though, is you don't even need THAT. In your class extension you can actually respecify @property declarations.

@interface SomeClass : NSObject
@property (nonatomic, readonly, strong) NSString *myProperty;
@end

@interface SomeClass()
@property (nonatomic, readwrite, strong) NSString *myProperty;
@end

Doing that, you just need to synthesize and you have a private setter that is synthesized for you.

Joshua Weinberg
  • 28,598
  • 2
  • 97
  • 90
  • 1
    Thanks Joshua - very useful! I've been, since, puzzling one final thing. Reading about ARC changes to properties [here](http://tools.ietf.org/html/draft-pantos-http-live-streaming-08) it seems that, by default, they are implemented by @synthesize with **strong** rather than **assign**. In which case, in the interests of making the public API cleaner, is it not best to just specify (nonatomic, readonly) as there's no need for users of the public interface to care or need to know that, internally, the property is strong? Hopefully I'm making sense here. :) – Quintin Willison May 24 '12 at 10:39
  • It is strong only for object types, to help make things more explicit I still like to put `strong`, `weak`, or `assign`. – Joshua Weinberg May 24 '12 at 14:51
  • Indeed strong is only applicable to object types but the question still remains as to whether your public API (ie header file) should need to publish this detail. That's the real point I was querying! – Quintin Willison May 25 '12 at 13:40
  • I prefer to make it do so as to be more explicit – Joshua Weinberg May 25 '12 at 14:54
  • I asked a similar question, I am not sure if it clears anything up (I am still vague on what goes on under the covers) http://stackoverflow.com/questions/10694676/what-is-the-correct-way-to-declare-a-readonly-property-for-ios-using-arc – Wayne Uroda Aug 14 '12 at 06:17
6

You can redeclare your property as readwrite in interface extension:

@interface SomeClass()
@property (nonatomic, strong, readwrite) NSString *myProperty;
@end
iHunter
  • 6,205
  • 3
  • 38
  • 56