Coordinate is readonly?


#1

I’ve found myself stuck while creating BNRMapPoint.

In the text it says to add the @property for coordinate like so

but then moment later, create a custom initializer like this

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

     if (self)
     {
          coordinate = c
          [self setTitle: t];
     }

     return self;
}

The problem I’m seeing is that in the declaration for coordinate, it’s set to readonly. That means that the compiler shows an error when I try and set coordinate to c in the initialiser.

Am I missing something about setting coordinate to not be readonly? I see a mention that you don’t have to make it readonly but no mention of actually changing the code to do this.


#2

Have you synthesized it? If not, there is no instance variable named coordinate.


#3

Turned out I had (CLLocationCoordinate2D *)c in the initWithCoordinate:title: method rather than (CLLocationCoordinate2D)c.

Thanks.


#4

So now my problem has been solved, can I ask a question regarding the @property declaration of coordinate?

In the @property directive it’s set as readonly, but we assign a value to it when we say coordinate = c. Does the “readonly” apply just to messages sent out-with the class, while within the class we can assign anything we like to coordinate regardless of it not having a setter?


#5

[quote=“MarkReid”]So now my problem has been solved, can I ask a question regarding the @property declaration of coordinate?

In the @property directive it’s set as readonly, but we assign a value to it when we say coordinate = c. Does the “readonly” apply just to messages sent out-with the class, while within the class we can assign anything we like to coordinate regardless of it not having a setter?[/quote]

I was wondering the same and thought of the same reason, can anyone confirm that?


#6

readonly means that no setter will be defined for other classes to leverage.

Thus, as you pointed out, the class can set and modify that instance variable as often as it likes by assigning directly to the variable.


#7

Then why is title set via the setter method instead of straight like the coordinate?


#8

If a setter is available, it’s generally better to use it so that if you add more sophisticated logic to the setter at a later date, all of your code takes advantage of it.

In an ideal world, you’d always use getters and setters, even within the class itself, so that you can trivially remove the instance variable entirely someday down the road if it seems appropriate to do so (e.g., to replace it with dynamic logic, or a database routine, or…). Since Objective-C doesn’t allow for private setters, however, this isn’t really practical (as far as I’m aware).


#9

As I understand it from the Objective-C book by Clair you can provide a “hidden” setter (for internal use) for properties that are declared as readonly by redeclaring the property with a readwrite attribute in an extension to the class’s .m file. If I’m following his example correctly it would be done in the following way in BNRMapPoint.m:

[code]
#import “BNRMapPoint.h”

@interface BNRMapPoint ()

@property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;

@end

@implementation BNRMapPoint

@synthesize coordinate, title;

  • (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)t
    . . . [/code]

However, following up on Pippah’s question my question is why are we using accessors at all within an initialization method? According to Clair initializers and dealloc methods are exceptions where instance variables should be set directly. Supporting this I find the following in the documentation:

[quote]Access Instance Variables Directly from Initializer Methods
Setter methods can have additional side-effects. They may trigger KVC notifications, or perform further tasks if you write your own custom methods.

You should always access the instance variables directly from within an initialization method because at the time a property is set, the rest of the object may not yet be completely initialized. Even if you don’t provide custom accessor methods or know of any side effects from within your own class, a future subclass may very well override the behavior.[/quote]