tags:

views:

173

answers:

2

I was trying to create a property which is readonly. I wanted to initialize with a value from the class creating an instance of this class, e.g.

@property (retain,readonly) NSString *firstName;

And I tried to initialize it like this:

-(id)initWithName:(NSString *)n{ self.firstName = n; }

Once I did this, the compiler reported an error that the readonly property cannot be assigned. So how can i do this ?

+1  A: 

Don't use the synthesized setter:

firstName = [n retain]; //Or copy

It is generally advised to bypass the setters in any init and dealloc methods anyway.

Rengers
The problem with my above implementation is that the value is not retained. Once i add the retain to the property, will this assignment set the value into property. And if some other object accesses this property will this value be there. I have also modified my question
tak
Why would this be a problem? Using `firstname = [n retain]` will just make firstName a pointer to `n`. So yeah, when some other object accesses this property, the value will be there. :)
Rengers
If I try to do it this way if I access this property, i am getting the following exception.Program received signal: “EXC_BAD_ACCESS”. And this error is not due to any other property. I investigated this a lot in debugger. This property shows "out of scope". And if I assign it with ,<code>self.firstName = n;</code>. then everything works fine.
tak
Ok, that is very weird. Using `firstname = [n retain]` just works for me. Anyway, if Ole Begemann's method work I guess thats fine.
Rengers
I was trying it without invoking the retain on n. After using this <code>firstname = [n retain]</code> it works perfectly fine. As far as i understand if we do a direct assignment the reference count remains the same (since we are skipping the @property setter)and we have to do it explicitly, increase the reference count. Thanks, this seems to be a perfect solution. Can you please edit your main answer, that would be great.
tak
+2  A: 

Either assign to the instance variable directly (don't forget to add a retain or copy if you need it) or redeclare the property in a private class extension. Like this:

In your .h file:

@property (readonly, copy) NSString *firstName;

In your .m file:

@interface MyClass ()

// Redeclare property as readwrite
@property (readwrite, copy) NSString *firstName;

@end


@implementation MyClass

@synthesize firstName;
...

Now you can use the synthesized setter in your implementation but the class interface still shows the property as readonly. Note that other classes that import your .h file can still call -[MyClass setFirstName:] but they won't know that it exists and will get a compiler warning.

Ole Begemann
This looks a nice workaround. Thanks.
tak