21

现代(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;
}

上面的内容与合成的 ivar 不兼容,因为它需要访问一个未在标头中声明的 ivar。由于各种原因,我想更新我的一些个人框架以在现代运行时使用合成 ivars,需要修改上述代码以使用合成 ivars 以实现该目标。

虽然 Objective C 2.0 文档声明现代运行时上的合成访问器将在首次使用时合成 ivar。它没有指定使用什么低级机制来执行此操作。是否由 class_getInstanceVariable() 完成,对 class_addIvar() 的限制是否松动,是否是目标 C 2.0 运行时中的未记录函数?虽然我可以为支持我的属性的数据实现自己的侧存储,但我更愿意使用合成访问器正在使用的机制。

4

3 回答 3

20

刚才我又去看了文档,我觉得你看错了。合成的 ivars 是在编译时创建的,而不是在运行时创建的。

根据Objective-C 2.0 文档

取决于运行时的行为存在差异(另请参见“运行时差异”):

对于旧版运行时,实例变量必须已经在 @interface 块中声明。如果存在与属性具有相同名称和兼容类型的实例变量,则使用它,否则会出现编译器错误。

对于现代运行时,实例变量是根据需要合成的。如果同名的实例变量已经存在,则使用它。

所以你需要做的就是声明你需要的实例变量,相同的代码将在两个运行时工作......

于 2008-11-08T20:17:31.217 回答
0

您正在寻找的是@synthesized 名称,例如:

@synthesize name = _name;

...

- (NSString *) name {
    if (!name) {
        _name = @"Louis";
    }

    return _name;
}
于 2012-01-28T13:51:50.457 回答
-6

您可以在运行时使用NSKeyValueCoding 协议添加属性。

[myObject setValue:@"whatever" forKey:@"foo"];
于 2011-04-04T18:49:44.243 回答