0

I have a Singleton class called Constants and I need to set some app wide constants in there. Id like these constants to be readonly. So I did the following in the Constants.h file

 @interface Constants : NSObject
 {

 }

 @property (nonatomic, readonly)double U_LAT;
 @property (nonatomic, readonly)double U_LNG;

Then in my .m fileI got this method

 -(id)init
 {
     self = [super init];

     self.U_LAT = 49.2765;
     self.U_LNG = -123.2177;

     return self;
 }

I get this error from this code:

 Assignment to readonly property

Can I not initialize my readonly variable in the init method? If not how do I initialize them?

Rachel Gallen
  • 27,943
  • 21
  • 72
  • 81
banditKing
  • 9,405
  • 28
  • 100
  • 157

3 Answers3

10

self.propertyName = val; is the same as [self setPropertyName:val]; -- it requires a setter method to exist. Read-only properties don't have setter methods.

You can set the ivar which backs the property directly, however:

-(id)init
 {
     self = [super init];

     _U_LAT = 49.2765;
     _U_LNG = -123.2177;

     return self;
 }

The ivar's name will be the property name prefixed with an underscore if you are allowing the properties to be synthesized automatically. If you have an explicit @synthesize propName;, the ivar will have the same name. You can also create a variable with any name you like, again using a synthesize statement: @synthesize cat = dog;

It's also 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.

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
5

I think the better way is to redeclare the property in a private interface, like this:

// .h

@interface Constants : NSObject
@property(nonatomic, readonly) double U_LAT;
@end

// .m

@interface Constants ()
@property(nonatomic, readwrite) double U_LAT;
@end

And yes, in inits and dealloc, refer directly to the variable as _U_LAT.

danh
  • 62,181
  • 10
  • 95
  • 136
  • Or better refer to them as `self.U_LAT`. – zaph Feb 02 '13 at 20:25
  • Zaph: it is strongly discouraged to use accessor methods (`self.foo`) during init. Better to use the underscore variable, `_foo`. – Olie Jul 02 '14 at 22:33
0

Better still to declare them not as properties but as constants.

In the .h file, add the following code above the @interface:

extern double const U_LAT;
extern double const U_LNG;

Then in the .m file, add the following code above the @interface:

double const U_LAT = 49.2765;
double const U_LNG = -123.2177;

The U_LAT and U_LNG will be available to any class that imports Constants.h, and you won't have to deal with properties or interfaces.

It's for exactly this sort of thing that const was invented.

Joel Derfner
  • 2,207
  • 6
  • 33
  • 45