4

I have an object that holds a dictionary JSONData. From the header file, and to the other classes that'll access it, I want this property to only be read-only and immutable.

@interface MyObject : NSObject

@property (readonly, strong, nonatomic) NSDictionary *JSONData;

@end

However, I need it to be readwrite and mutable from the implementation file, like this, but this doesn't work:

@interface MyObject ()

@property (readwrite, strong, nonatomic) NSMutableDictionary *JSONData;

@end

@implementation MyObject

// Do read/write stuff here.

@end

Is there anything I can do to enforce the kind of abstraction I'm going for? I looked at the other questions and while I already know how to make a property readonly from .h and readwrite from .m, I can't find anything about the difference in mutability.

Matthew Quiros
  • 13,385
  • 12
  • 87
  • 132

1 Answers1

7

You need a separate private mutable variable in your implementation. You can override the getter to return an immutable object.

@interface MyObject () {
  NSMutableDictionary *_mutableJSONData;
}
@end

@implementation MyObject 

// ...

-(NSDictionary *)JSONData {
   return [NSDictionary dictionaryWithDictionary:_mutableJSONData];
}

// ...
@end

No need to implement the setter, as it is readonly.

Mundi
  • 79,884
  • 17
  • 117
  • 140
  • Yup, I actually just found my own way to this solution too. NOTE: **DO NOT** use `self.rawData[@"key"] = @"value"` anywhere in the implementation because it won't work. `_rawData[@"key"] = @"value"`, however, will, because you're accessing the instance variable instead of the property (declared immutable). Do I really need to override the getter though? – Matthew Quiros Jan 14 '14 at 09:03
  • Yes. You are returning a different class of object. – Mundi Jan 14 '14 at 09:07
  • ^Ah, right. If I'm not mistaken, the compiler won't complain, but if I don't override the getter, it will return an `NSMutableDictionary` instance with the modifier methods inaccessible. – Matthew Quiros Jan 14 '14 at 09:14
  • 2
    Note that you can no longer use KVO on JSONData if you do this. – Wil Shipley Jan 14 '14 at 10:31
  • Good point. On the basis of the level of the question, though, I think that was not to be expected. – Mundi Jan 14 '14 at 14:05
  • @MattQuiros, if you want property access in implementation (i.e. `self.rawData`) look at [this solution](http://stackoverflow.com/a/10540765). – Franklin Yu Apr 03 '16 at 04:18
  • That's essentially the same as mine, only less simple. My `()` indicates also a category. – Mundi Apr 03 '16 at 09:25