如果我理解正确,在 Objective-C 中,属性会自动使用 getter 和 setter 合成,实例变量声明为属性名称,并在前面加上下划线 ( _ivar
)。
所以,这段代码:
主文件
#import <Foundation/Foundation.h>
#import "hello.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
Hello *hello = [[Hello alloc] init];
NSLog(@"%@", hello.myString);
return 0;
}
}
你好.h
#import <Foundation/Foundation.h>
@interface Hello : NSObject
@property (copy, nonatomic) NSString *myString;
@end
你好.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 属性更改为只读时,如下所示:
@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
所以,我的问题是,为什么readonly
在属性上使用时它不会自动合成下划线 ivar?还是我完全错误地理解了这个 Objective-C 的东西是如何工作的?
我非常感谢一个解释性的答案,因为我真的很想了解到底发生了什么以及为什么。
先感谢您。