5

我对为什么有些类声明属性但不声明 ivar 感到困惑,反之亦然。

在声明实例变量时也将其声明为属性是否是标准做法?

例子:

@interface AppDelegate : NSObject <UIApplicationDelegate>
{
    UIWindow *window;
    UINavigationController *navigationController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

在声明一个类的 ivar 以使其成为属性时,这只是标准做法吗?

我知道@property 创建了自己的细长设置器(和@synethesize 的getter),但为什么它也需要是一个ivar?

4

1 回答 1

14

它没有。

在过去,ivars 需要在@interface. 这实际上仍然适用于 PPC 和 i386(即 32 位英特尔)目标。这是因为脆弱的基类问题,它要求所有子类都知道其超类的确切大小。因此,ivars 需要在@interface或没有人可以子类化该类。

随着转向 x86_64 和 ARM,与 obj-c 2.0 一起修复了脆弱的基类问题。有了这个修复,类大小不再需要在编译时知道,而是可以推迟到运行时。因此,ivars可以在其他地方声明。值得注意的是,现在可以从 a @property(更具体地说是@synthesize实现中的行)合成 ivar。在 Clang 中,它们也可以在类扩展块(看起来像@interface ClassName ())中声明,或者直接在@implementation.

今天,您发现在块中声明的 ivars 有 3 个原因@interface

  1. 尚未更新以利用隐藏 ivar 声明的能力的旧代码(或具有旧习惯的程序员)。
  2. 需要在 PPC 或 i386 上运行的代码。
  3. 无论出于何种原因,都希望他们的 ivars 公开的代码。绝不应该是这种情况。

当今天编写不需要针对旧运行时的代码时,您应该从您的属性(首选)合成您的 ivars,或者如果您需要不与属性绑定的 ivars,您应该在类扩展中声明它们或你的@implementation. 这样做的主要原因是因为头文件记录了您的类的公共 API,并且不应包含任何不公开的内容。Ivar 不是公开的,因此不应该在头文件中。

于 2012-08-18T02:31:32.210 回答