Если я правильно понимаю, в Objective-C свойства автоматически синтезируются с помощью геттеров и сеттеров, при этом переменная экземпляра объявляется как имя свойства с добавленным подчеркиванием (_ivar
).
Итак, этот код:
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
Может быть скомпилирован и запущен следующим образом:
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
Теперь, когда я изменяю свойство myString для readonly следующим образом:
@property (readonly, copy, nonatomic) NSString *myString;
Затем, когда я пытаюсь скомпилировать, я получаю сообщение об ошибке:
hello.m:11:9: error: unknown type name '_myString'; did you mean 'NSString'?
_myString = @"Hello";
^~~~~~~~~
NSString
Так что _myString
не определено. Не компилятор не синтезировал свойство с переменной экземпляра _myString? Посмотрите, работает ли это, когда я сам синтезирую его:
В реализации hello.m:
@synthesize myString = _myString;
Теперь он снова работает:
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
Итак, мой вопрос: почему он не автоматически синтезируется с подчеркиванием ivar, когда вы используете readonly
для свойств? Или я полностью ошибаюсь в понимании того, как это работает Objective-C?
Я очень благодарен за объяснительный ответ, поскольку я действительно хочу понять, что именно происходит и почему.
Спасибо заранее.