在实现接口时,教程和文献中常见的方法似乎是声明一个ivar,然后设置@property
和@synthesize
。
@interface MyClass : NSObject {
NSString *myString;
}
@property (nonatomic, retain) NSString *myString;
@end
但是,省略显式声明而只使用@property也有同样的效果。
@interface MyClass: NSObject {
}
@property (nonatomic, retain) NSString *myString;
@end
那么为什么大多数人使用@property
和显式声明呢?不这样做不好吗?
过去是必须的。Objective-C运行时有两个不同的版本:一个只有32位的"遗留"运行时(旧版本)和一个32/64位运行时(新的32位运行时仅用于iOS设备和iOS模拟器)。
我认为唯一的地方,这仍然是必要的,当你运行应用程序在32位模式(无论是10.5或10.6)。其他任何地方(64位Leopard、64位Snow Leopard、Lion、iOS)都使用具有"自动ivar合成"的新运行时,生成的ivar被称为"合成ivars"。
有些平台支持合成实例变量,有些则不支持。显式声明实例变量使您的代码在更多地方有效,并且直到最近它都是完全必要的,所以人们仍然这样做。几年后,他们可能不会再这样做了。
使用现代版本的Xcode(任何关于4.2或更高版本),没有理由在你的头文件中声明一个iVar,永远。任何可公开访问的东西都应该声明为属性。
许多人忘记了Objective C对象实际上是指向C结构体的指针。因此,在头文件中声明的任何iVar都可以使用myObject->myPublicIVar
通过传递getter和setter直接访问。特别是在非arc代码中,这是非常危险的。@private
指令防止使用->
操作符访问iVars,但仍然使头文件混乱。如果有更好的方法,@private
就没有意义了。
任何私有的东西都应该在你的。m文件中声明。通常,这需要一个类扩展,像这样:
// The .h file
@interface Foo : NSObject
@property (nonatomic, strong) NSString *myPublicString;
@end
// The .m file
@interface Foo ()
@property (nonatomic, strong) NSString *myPrivateString;
@end
@implementation Foo {
NSString *myPrivateIVar;
}
// Xcode 4.5 or later will not require these @synthesize
@synthesize myPublicString = _myPublicString;
@synthesize myPrivateString = _myPrivateString;
@end
这样的实现提供了一个由iVar支持的公共属性,一个由iVar支持的私有属性,以及一个私有的独立iVar。我已经包含了@synthesize指令,但它们不是使用现代工具所必需的。
@property只实现了访问方法,实例变量本身必须存在。如果尝试忽略变量,它将在运行时失败,如果不是在编译时。