现代 Objective C 运行时中 ivar 合成的底层机制是什么

发布于 2024-07-08 18:36:33 字数 786 浏览 13 评论 0原文

现代(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() 的限制是否放宽?它是 Objective C 2.0 运行时中未记录的函数吗? 虽然我可以为支持我的属性的数据实现自己的侧面存储,但我更愿意使用合成访问器正在使用的机制。

One of the features of the modern (64 bit OS X and iPhone OS) Objective C runtime is the ability for properties to dynamically synthesize ivars without explicitly declaring them in the class:

@interface MyClass : NSObject {
//  NSString *name; unnecessary on modern runtimes
}

@property (retain) NSStrng *name;

@end

@implementation MyClass

@synthesize name;

@end

In quite a bit of my code I use custom getter implementations in order to initialize the properties:

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

  return name;
}

The above is incompatible with synthesized ivars since it needs to access a an ivar that is not declared in the header. For various reasons I would like to update a number of my personal frameworks to use synthesized ivars when built on the modern runtimes, the above code needs to be modified to work with synthesized ivars in order to achieve that goal.

While the Objective C 2.0 documentation states that the synthesized accessors on the modern runtime will synthesize the ivar on first use. It does not specify what low level mechanism is used to do this. Is it done by class_getInstanceVariable(), are the restrictions on class_addIvar() loosened, is it an undocumented function int he objective C 2.0 runtime? While I could implement my own side storage for the data backing my properties, I would much rather use the mechanism that synthesized accessors are using.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

悲喜皆因你 2024-07-15 18:36:33

我刚才又去看了文档,我认为你误读了。 综合的 ivar 是在编译时创建的,而不是在运行时创建的。

根据 Objective-C 2.0 文档

依赖于运行时的行为存在差异(另请参阅“运行时差异”):

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

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

因此,您需要做的就是声明您需要的实例变量,并且相同的代码将在两个运行时上运行......

I went and looked at the documentation again just now, and I think you're misreading it. Synthesized ivars are created at compile time, not at run time.

According to the Objective-C 2.0 documentation:

There are differences in the behavior that depend on the runtime (see also “Runtime Differences”):

For the legacy runtimes, instance variables must already be declared in the @interface block. If an instance variable of the same name and compatible type as the property exists, it is used—otherwise, you get a compiler error.

For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.

So all you need to do is declare the instance variable you need, and the same code will work on both runtimes...

只涨不跌 2024-07-15 18:36:33

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

@synthesize name = _name;

...

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

    return _name;
}

What you are looking for is @synthesized name, like:

@synthesize name = _name;

...

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

    return _name;
}
情魔剑神 2024-07-15 18:36:33

您可以在运行时使用 NSKeyValueCoding 协议

[myObject setValue:@"whatever" forKey:@"foo"];

You add properties at run-time with the NSKeyValueCoding Protocol.

[myObject setValue:@"whatever" forKey:@"foo"];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文