0

I use the following to expose languages array.

@property(nonatomic,readonly)NSArray *languages;

Assigning languages before ARC was like this:

languages=[[NSArray arrayWithObjects:
               [[Language alloc]initWithCode:@"es"],
               [[Language alloc]initWithCode:@"en"],
               nil] retain];

So, I was both able to retain the object and also mark it as readonly to outside.

With ARC, As I cannot type "retain" manually. How can I do this without overriding setters and getters? Is there a way to mark a property both readonly (to outside) and retain (to inside) for ARC?

frankish
  • 6,738
  • 9
  • 49
  • 100
  • possible duplicate of [objective-c ARC readonly properties and private setter implementation](http://stackoverflow.com/questions/8566671/objective-c-arc-readonly-properties-and-private-setter-implementation) – Rod Oct 08 '13 at 15:46

1 Answers1

3

retain* and readonly really have nothing to do with each other. readonly indicates that the property only has a getter, not a setter. retain means that the class maintains a retaining (strong) reference to the object referenced by the property, and under ARC, assuming the property is backed by an underlying, synthesized instance variable, means that the instance variable is a __strong variable.

If you want a property that is read-only to the outside world, but can be read and written inside the class, you can redeclare the property as readwrite in a class extension in your implementation (.m) file. In the header:

@property (nonatomic, strong, readonly) NSArray *languages;

Then, at the top of your .m:

@interface YourClass ()
    @property (nonatomic, strong, readwrite) NSArray *languages;
@end

Inside the class's implementation, you can now use self.languages = ...;, (or _languages = ...; in the initializer) to set the languages property. This is not actually different under ARC vs. non-ARC...

*Under ARC, it's more customary to use strong instead of retain, but the compiler treats them the same way.

Andrew Madsen
  • 21,309
  • 5
  • 56
  • 97
  • 3
    You don't need to explicitly declare the property as `readwrite` in the class extension as properties are `readwrite` by default. – neilco Oct 08 '13 at 15:59
  • 1
    And for the outside world, objects would only access the one that is readonly; and, either within the class or to the outside world, the same NSArray is referenced? Just to please my curiosity: if we set both properties above to "atomic", would there be any extra work for us to do, when within the class languages is being written and some objects outside of this class is trying to read it? Thanks. – Unheilig Oct 08 '13 at 16:00
  • @neilco, that's true. I prefer to be explicit about what's going on. – Andrew Madsen Oct 08 '13 at 17:56
  • @Unheilig, (Had a whole comment typed out and lost it to an accidental back swipe on my Magic Mouse. Grr...) I'm not 100% sure what you're asking, but in short, yes, the same NSArray is used by both the (public) getter and the (private) setter. Regarding `atomic`, that has nothing to do with `retain` or `readonly`. In short it means that even if the getter and setter are called simultaneously from different threads, the getter will return a complete (valid) value. It does not guarantee 'thread safety', but can be part of a thread safe design. – Andrew Madsen Oct 08 '13 at 18:01
  • @AndrewMadsen As far as Magic Mouse goes - agree - it bears its name faithfully - "Now you compose, and now it's gone! Magic!" :-) Jokes aside, thanks for your explanation. +1 – Unheilig Oct 08 '13 at 18:36