If I understand correctly, in Objective-C, properties are automatically synthesized with getters and setters, with the instance variable declared as the property name with an underscore prepended (_ivar
).
So, this code:
main.m
#import <Foundation/Foundation.h>
#import "hello.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
Hello *hello = [[Hello alloc] init];
NSLog(@"%@", hello.myString);
return 0;
}
}
hello.h
#import <Foundation/Foundation.h>
@interface Hello : NSObject
@property (copy, nonatomic) NSString *myString;
@end
hello.m
#import "hello.h"
@implementation Hello
-(Hello *)init
{
if (self = [super init]) {
_myString = @"Hello";
}
return self;
}
-(NSString *)myString
{
return [NSString stringWithFormat:@"%@ %@", _myString, @"World"];
}
@end
Can be compiled and run like this:
bash-3.2$ clang -framework Foundation main.m hello.m -o hello
bash-3.2$ ./hello
2013-05-27 13:20:39.738 hello[23320:707] Hello World
Now when I change the myString property to readonly like this:
@property (readonly, copy, nonatomic) NSString *myString;
Then when I try to compile I get an error:
hello.m:11:9: error: unknown type name '_myString'; did you mean 'NSString'?
_myString = @"Hello";
^~~~~~~~~
NSString
So _myString
is not defined. Did the compiler not synthesize the property with instance variable _myString? Let's see if it works when I synthesize it myself:
In hello.m implementation:
@synthesize myString = _myString;
Now it works again:
bash-3.2$ clang -framework Foundation main.m hello.m -o hello
bash-3.2$ ./hello
2013-05-27 13:36:59.916 hello[24219:707] Hello World
So, my question is, why is it not automatically synthesized with an underscore ivar when you use readonly
on properties? Or am I totally on the wrong path of understanding how this Objective-C stuff works?
I would very much appreciate an explaining answer, as I really want to understand what's exactly happening and why.
Thank you in advance.