现代(64位OS X和iPhone OS)的一个特性Objective C运行时是属性动态合成ivars而无需在类中明确声明它们的能力:
@interface MyClass : NSObject {
// NSString *name; unnecessary on modern runtimes
}
@property (retain) NSStrng *name;
@end
@implementation MyClass
@synthesize name;
@end
在我的相当多的代码中,我使用自定义getter实现来初始化属性:
- (NSString *) name {
if (!name) {
name = @"Louis";
}
return name;
}
以上与合成的ivars不兼容,因为它需要访问未在标题中声明的ivar。出于各种原因,我想更新一些我的个人框架,以便在现代运行时构建时使用合成的ivars,需要修改上述代码以使用合成的ivars来实现该目标。
虽然Objective C 2.0文档指出现代运行时的合成访问器将在首次使用时合成ivar。它没有指定使用什么低级机制来执行此操作。它是由class_getInstanceVariable()完成的,对class_addIvar()的限制是否松散,是否是一个未记录的函数在客观的C 2.0运行时?虽然我可以为支持我的属性的数据实现自己的副存储,但我更愿意使用合成访问者正在使用的机制。
答案 0 :(得分:21)
我刚才再次查看了文档,我认为你误读了它。合成的ivars是在编译时创建的,而不是在运行时创建的。
根据Objective-C 2.0 documentation:
依赖于运行时的行为存在差异(另请参阅“运行时差异”):
对于遗留运行时,必须已在@interface块中声明实例变量。如果存在与属性相同名称和兼容类型的实例变量,则使用它 - 否则,您将收到编译器错误。
对于现代运行时,根据需要合成实例变量。如果已存在同名的实例变量,则使用它。
所以你需要做的就是声明你需要的实例变量,相同的代码将适用于两个运行时......
答案 1 :(得分:0)
您正在寻找的是@synthesized名称,例如:
@synthesize name = _name;
...
- (NSString *) name {
if (!name) {
_name = @"Louis";
}
return _name;
}
答案 2 :(得分:-6)
您可以在运行时使用NSKeyValueCoding Protocol添加属性。
[myObject setValue:@"whatever" forKey:@"foo"];