13

I have following code:

-(id) initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
    self = [super init];

    if (self)
    {
        coordinate = c;
        self.title = t;
    }

    return self;
}

where coordinate is:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

I had two questions:

  • is it OK to assign to a property that is readonly?
  • should not coordinate have self before it? (e.g., self.coordinate = c).

ps. I don't get any errors using this code - and it is an example from a book.

4

8 回答 8

15

You should write: self.coordinate = c which is equal to [self setCoordinate:c] - calling setter method. But you can't do this because you will get Assignment to readonly property error. Read-only properties don't have setter methods.In your case you just set the ivar which backs the property directly and it is well documented behavior. The ivar name will be the property name prefixed with an underscore BUT as in your case you have an explicit @synthesize as you said, so the ivar will have the same name and that's why you haven't any compiler issues. It is possible for the property to be read-only publicly, but be writeable by the class - this involves either declaring a setter method in a class extension or redeclaring the property in the extension. For this you can refer this post: Objective-C property that is readonly publicly, but has a private setter

于 2013-07-18T11:15:12.050 回答
3
  • is it OK to assign to a property that is readonly?

    Yes, its okay if you don't want a property to be mutated outside its containing instance.

    eg: count property of an array, here count is a property that is dependent on the number of objects retained by the array. So it shouldn't be modified from outside the Array object.

  • should not coordinate have self before it? (e.g., self.coordinate = c).

    If read only, you can't modify your property via a setter method.

    self.coordinate translates to [self setCoordinate:] which is not permitted as read only prevents setter methods from modifying the property.

So you should directly set the ivar, and this can be done only from inside the object for which readonly property is defined.

i.e

_coordinate = value; //or coordinate = value if you have synthesized it. 

If you are curious,

self.propertyName && self.property = indirectly calls getter and setter method.

And in implementation, setters and getter help the _ivars to be public-ally accessible is the property is public.

- (void)setProperty(value) //self.property = value
 {
    _property = value;
 }

- (id)property  //self.property
  {
     return _property;
  }
于 2013-07-18T11:23:48.703 回答
1

you cannot assign value to variable with readonly property, but from iOS6, the @synthesize can be added automatically, so you can use ivar to replace it. Like _test = @"test" to replace self.test = @"test" if the property of test is readonly.

于 2015-07-06T06:23:21.287 回答
0
  1. No that is not ok. Proper way to assign readonly is like this:

    - (CLLocationCoordinate2D)coordinate {
    
        //create the struct and return it.
    
        return value;
    
    }
    
  2. No it is the other way around. You should set title like this:

    _title = t;
    
于 2013-07-18T11:15:56.670 回答
0

The line coordinate = c; is not assigning the property, it's assigning the instance variable which has the same name. It is not possible to assign a readonly property, that's what “read only” means. If you change it to self.coordinate = c you will get an error, unless this property is redeclared as readwrite in class extension.

于 2013-07-18T11:22:04.620 回答
0

is it OK to assign to a property that is readonly?

If you use synthesized accessors like you're doing, it's perfectly fine.

should not coordinate have self before it? (e.g., self.coordinate = c).

self.coordinate is a shortcut for the non synthesized accessor. This setter is visible from outside the class, so since the property should be readonly for class users, you get a compiler error if you try to access readonly properties with the dot notation. Your code is correct.

于 2013-07-18T11:24:23.573 回答
0

is it OK to assign to a property that is readonly?

If you @synthesize coordinate;, then the backing ivar will be named coordinate. If the property is auto-synthesized, it will be named _coordinate.

If your intent is to assign to the underlying instance variable within the initializer, that is fine (e.g. coordinate = c or _coordinate = c).

If you want to set it using the setter (e.g. [self setCoordinate:c] or self.coordinate = c; you would need to implement the setter yourself or synthesize its definition (e.g. by declaring the property readwrite in your class continuation).


should not coordinate have self before it? (e.g., self.coordinate = c).

No, it should not. Use direct access in a partially constructed state, such as an initializer or -dealloc.

Given the properties:

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy, readwrite) NSString * title;

Your initializer should take the form:

- (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
{
 self = [super init];

 if (self)
 {
  _coordinate = c;
  _title = t.copy; // note: copy/ownership semantics match property declaration
 }

 return self;
}

@end
于 2013-07-18T11:49:27.810 回答
0

I've seen tricky people do this....

Source.h

@property (readonly) BOOL  isRunning;

Source.m

- (void) blahBlahBlah { ...
   self->_isRunning = YES; ...

There is very little documentation that I can find about these types of accessors... I'm pretty sure it is just a standard C construct... one which I am not very familiar... But this is a way to go if your mastery of the subject.. is better than mine...

于 2013-10-05T02:55:24.680 回答