属性与实例变量

GPP*_*GPP 5 properties object objective-c ivar

我很困惑为什么有些类声明了一个属性但没有声明一个ivar,反之亦然.

声明实例变量同时将其声明为属性是标准做法吗?

例:

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

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
Run Code Online (Sandbox Code Playgroud)

宣布一个班级的ivar使其成为一个属性时,这只是标准做法吗?

我知道@property创建了自己的拉长的setter(和@synethesize的getter),但为什么它也需要成为一个ivar?

Lil*_*ard 14

它没有.

在过去,人们需要宣布伊娃@interface.对于PPC和i386(即32位英特尔)目标,这实际上仍然是正确的.这是因为脆弱的基类问题,要求所有子类都知道其超类的确切大小.因此,ivars需要在@interface或者没有人可以继承类.

随着迁移到x86_64和ARM,与obj-c 2.0一起解决了脆弱的基类问题.通过此修复,不再需要在编译时知道类大小,而是可以将其延迟到运行时.因此,ivars可以在其他地方宣布.值得注意的是,现在可以从@property(更具体地说@synthesize,实施中的线)合成ivar .在Clang中,它们也可以在类扩展块(看起来像@interface ClassName ())或直接在@implementation.

今天,有三个原因可以解释为什么你会发现块中声明的ivars @interface:

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

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

  • @GPP:这在某种程度上取决于个人喜好.一般来说,我会说obj-c对象应该始终是属性.但对于C数据类型,您可能认为您更喜欢直接使用ivars.或者您可能更喜欢使用属性.随你(由你决定.请注意,如果您需要"私有"属性,则应在.m文件的类扩展中声明它. (2认同)