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


101

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

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


为什么第二个粗体的“ MyObject.h”不是“ MyObject.m”?
Ríomhaire

Answers:


93

如果您使用的是现代的Objective-C运行时(这是无论是iOS版3.x或更高,或64位雪豹或更高),那么你就不会需要在这样的情况下,以高德定义为您的属性。

当您拥有@synthesize该物业时,ivar实际上也将为您合成。这可以解决“脆弱易变”方案。您可以在《可可与爱》中阅读更多相关内容


71

在您的界面中,您可以在花括号之间或通过花@property括号外或在两者之间正式声明实例变量。无论哪种方式,它们都成为类的属性。区别在于,如果您声明@property,则可以使用来实现@synthesize,它会自动为您的getter / setter编码。例如,自动编码器设置器会初始化整数并将其浮动为零。如果您声明了实例变量,并且不指定相应的@property,那么您将无法使用@synthesize并且必须编写自己的getter / setter。

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

@property声明方法还允许你其他的选项,如retainreadonly,该实例变量声明方法没有。基本上,这ivar是旧的方式,并且@property对其进行了扩展并使其更加新颖/便捷。您可以使用self来引用。是否有前缀,只要名称对于该类是唯一的都没有关系。否则,如果您的超类具有与您相同的属性名称,那么您必须说出self.name或super.name之类的名称,以便指定您在谈论的名称。

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

希望这有助于清除周围浮现的所有混乱和错误信息。


现在已经不是强制性的@synthesize了,那么在这种情况下这个答案怎么有效!
raaz 2013年

您不必声明<code> @property ... @ synthesize </ code>。使用synthesize使您不必在实现中编写getter / setter。如果您不进行合成,则必须使用自己的吸气机/吸气机
-PapaSmurf

2
@PapaSmurf那是不正确的。您可以使用@property而不@synthesize自己使用也不实现它们。编译器将为synthesize您自动完成,而无需再编写了。
jbrennan

8

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


3

从文档中:

通常,现代和传统运行时的属性行为都是相同的(请参见《 Objective-C运行时编程指南》中的“运行时版本和平台”)。主要区别在于:现代运行时支持实例变量综合,而传统运行时不支持。

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


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;

1

Objective-C编程语言:属性实现指令

访问者综合行为的差异取决于运行时(另请参见“运行时差异”):

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.