声明的属性是否需要相应的实例变量?

时间:2010-06-19 03:48:56

标签: objective-c instance-variables declared-property

Objective-C 2.0中的属性是否需要声明相应的实例变量?例如,我习惯这样做:

MyObject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

但是,如果我这样做会怎么样:

MyObject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

这仍然有效吗?它与我之前的例子有什么不同吗?

6 个答案:

答案 0 :(得分:94)

如果您使用的是Modern Objective-C Runtime(iOS 3.x或更高版本,或64位Snow Leopard或更高版本),那么需要为您的属性定义ivars在这种情况下。

当您@synthesize属性时,ivar实际上也将为您合成。这绕过了“脆弱的伊娃”情景。您可以在Cocoa with Love

上详细了解相关信息

答案 1 :(得分:71)

在界面中,您可以在大括号之间或通过大括号外的@property或两者正式声明实例变量。无论哪种方式,它们都成为班级的属性。不同之处在于,如果您声明@property,那么您可以使用@synthesize来实施,它会为您自动编码您的getter / setter。例如,自动编码器设置器将整数和浮点数初始化为零。如果您声明了一个实例变量,并且没有指定相应的@property,那么您就不能使用@synthesize必须编写您自己的getter / setter。

您可以通过指定自己的getter / setter来覆盖自动编码的getter / setter。这通常使用延迟加载的managedObjectContext属性来完成。因此,您将managedObjectContext声明为属性,然后再编写-(NSManagedObjectContext *)managedObjectContext方法。回想一下,与实例变量/属性同名的方法是“getter”方法。

@property声明方法还允许您使用其他选项,例如retainreadonly,实例变量声明方法不会。基本上,ivar是旧的方式,@property扩展它并使其变得更加漂亮/更容易。你可以参考使用自我。前缀或不是,只要名称对该类是唯一的,它就没有关系。否则,如果您的超类具有与您相同的属性名称,那么您必须说出self.name或super.name,以指定您正在谈论的名称。

因此,您会看到越来越少的人在大括号之间声明ivar,而是转向仅指定@property,然后执行@synthesize。如果没有相应的@synthesize,您就无法在实施中执行@property。 Synthesizer只知道@property规范中的属性类型。 synthesize语句还允许您重命名属性,以便您可以在代码中通过一个名称(简写)引用属性,但在.h文件外部使用全名。然而,由于XCode现在具有非常酷的自动完成功能,这不是一个优势,但仍然存在。

希望这有助于消除所有混乱和错误信息。

答案 2 :(得分:8)

它可以双向工作,但是如果你不在花括号中声明它们,你就不会在xcode中的调试器中看到它们的值。

答案 3 :(得分:3)

来自文档:

通常,属性的行为在现代和传统运行时都是相同的(请参阅Objective-C运行时编程指南中的“运行时版本和平台”)。有一个关键区别:现代运行时支持实例变量合成,而遗留运行时则不支持。

要使@synthesize在遗留运行时中工作,您必须提供具有相同名称和属性的兼容类型的实例变量,或者在@synthesize语句中指定另一个现有实例变量。对于现代运行时,如果您不提供实例变量,编译器会为您添加一个。

答案 4 :(得分:3)

如果您使用的是XCode 4.4或更高版本,它将为您生成实例变量合成代码。

你只需声明如下属性;它将为您生成合成代码和实例变量声明代码。

@property (nonatomic, strong) NSString *name;

它将生成合成代码

@synthesize name = _name;

您可以使用_name访问实例变量 它类似于声明

NSString* _name

但如果你声明只读属性就像

@property (nonatomic, strong, readonly) NSString *name;

它会生成代码

@synthesize name;

@synthesize name = name; 

所以你应该访问带有前缀“_”的即时变量名 你可以用任何方式编写自己的合成代码,然后编译器会为你生成代码。 你可以写

@synthesize name = _name;

答案 5 :(得分:1)

The Objective-C Programming Language: Property Implementation Directives

  

访问者合成的行为有所不同,这取决于运行时(另请参阅“运行时差异”):

     
      
  • 对于旧版运行时,实例变量必须已在当前类的@interface块中声明。如果存在与该属性同名的实例变量,并且其类型与属性的类型兼容,则使用它 - 否则,您将收到编译器错误。

  •   
  • 对于现代运行时(请参阅Objective-C运行时编程指南中的“运行时版本和平台”),可根据需要合成实例变量。如果已存在同名的实例变量,则使用它。

  •