假设我们有一个Foo
类,其属性为bar
在标题中声明如下:
@interface Foo : NSObject {
int bar;
}
@property (nonatomic, assign) int bar;
@end
在.m我当然有@synthesize bar;
。
现在,我的问题是,如果删除int bar;
行,属性的行为方式相同,那么该行真的有必要吗?我错过了一些基本概念吗?
谢谢!
答案 0 :(得分:3)
如果没有与属性同名的实例变量(ivar),现代运行时会创建一个指定属性名称的新ivar,以便在看到@synthesize时保存属性值。
如果您的属性未定义为非原子并且您希望您的代码是线程安全的,那么它可能会帮助您不引用ivar(无论您是声明它还是它已被合成),因为这将阻止您在属性时直接访问它正在改变。据我所知,没有办法获得@synthesize为原子属性获取的同一个锁,因此你不能通过其合成访问器执行原子属性的ivar的安全读取(除非你编写一个显式的setter并锁定一些东西)你自己)。 If you are interested in writing you own accessors I have a blog post on that here.
我认为对每个属性都有一个明确的ivar更常见,但这可能是因为大多数代码都旨在与遗留运行时兼容,而不是因为它本质上是一种良好的实践。
编辑:我已更正第1段,说合成的ivar具有该属性的名称;我在Apple的文档中看不到它的名字有任何讨论,所以我认为它不是用户可访问的。感谢评论者指出这一点。
答案 1 :(得分:3)
“现代”Objective-C运行时会在遇到@synthesize
时自动生成ivars。
跳过它们的好处:
@property
给出了ivar的类型,名称和用途(属性!),所以你不会丢失任何东西。有几点需要注意:
由于调试器问题,目前我明确地添加了所有我的ivars并将它们标记为:
@interface Foo : NSObject {
#ifndef SYNTHESIZED_IVARS
int ivar;
#endif
}
@property (nonatomic, assign) int bar;
@end
我的计划是在确认调试器能够显示ivars后删除该块。 (据我所知,这已经发生了。)
答案 2 :(得分:2)
在最新的Objective-C运行时,事实证明所有的ivars(在本例中为bar)都是从@ property / @ synthesize声明动态添加到类中的,并且在类头中不需要相应的ivar声明。唯一需要注意的是,支持此功能的最新Objective-C运行时不包括对32位应用程序的支持。
来自优秀page的Cocoa with Love blog解释了更多。
答案 3 :(得分:1)
如果您正在使用现代的Obj-C运行时(例如,使用Xcode 4中的LLVM编译器),编译器可以自动为您创建实例变量。在这种情况下,您不需要声明ivar。
现代运行时由iOS,iOS模拟器和64位Mac OS X支持。您无法使用现代运行时为32位OS X构建项目。
答案 4 :(得分:0)
我相信它只能在64位模式下运行。如果你尝试为32位目标构建,它将抛出异常。
Scott Stevenson对objective-c 2更改有一个很好的概述,并提到64位运行时更改here