68

I'd like to use the @property syntax to declare a synthesized property that is publicly readonly but has a setter that can be called privately from within the class.

Since it's Objective-C, this basically means that the setFoo: method would be synthesized, but calling it outside of the class itself would result in a warning (unrecognized selector). To trigger the warning I have to declare the property readonly; is there any way to force a synthesized setter that is only available within the class?

Adam Ernst
  • 52,440
  • 18
  • 59
  • 71

2 Answers2

116

I think what you're looking for are called class extensions. You would declare the property read-only in the header:

@interface MyClass : NSObject {
}

@property (readonly, assign) NSInteger myInteger;

@end

Then redeclare in your class extension in the implementation file:

@interface MyClass ()

@property (readwrite, assign) NSInteger myInteger;

@end


@implementation MyClass

@end

For more check out Apple's documentation

Lukas Spieß
  • 2,478
  • 2
  • 19
  • 24
Sean Rich
  • 2,338
  • 2
  • 20
  • 15
  • 1
    You're correct, see also http://stackoverflow.com/questions/743586/synthesizing-properties-in-categories/3251621#3251621 – Adam Ernst Feb 15 '11 at 19:17
  • 3
    This is a great way to leverage the convenience of properties while maintaining necessary encapsulation. :) Love this capability. – CIFilter Feb 15 '11 at 21:03
  • 5
    Updated documentation link: http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW3 – Aaron Brager May 16 '13 at 17:58
  • 1
    Did anyone actually test this? Attempting to set the property using dot notation gets a compiler error (good), but using the setMyInteger: method only gets a compiler warning, and when the app is run the "readonly" property does get changed. – jk7 Jun 14 '16 at 01:25
  • 1
    @jk7 That is correct behavior; the compiler is telling you you are doing it wrong. The runtime is "free" to violate this. – bbum Dec 05 '19 at 20:52
1

I might be late, but without extension i did using the following technique

@interface MyClass : NSObject {
 NSString * name;
}

@property (readonly, strong) NSString * name;

@end

on the other hand in implementation file

@implementation MyClass
 @synthesize name;

 - (id)initWithItems:(NSDictionary *)items {
self = [super init];
if(self)
{ 
  name = @"abc";
}

return self;
}

@end

doing so it will set your value and will be accessible as readonly. Thanks.

Majid Bashir
  • 558
  • 1
  • 4
  • 27