Objective-c 中的 @property 和 @synthesize

Posted

技术标签:

【中文标题】Objective-c 中的 @property 和 @synthesize【英文标题】:@property and @synthesize in objective-c 【发布时间】:2011-04-28 06:56:53 【问题描述】:

当我在玩游戏并弄清楚https://github.com/enormego/EGOTableViewPullRefresh 的工作原理时,我发现@property 和@synthesize 很神秘。这是我提到的代码

EGORefreshTableHeaderView.h

@interface EGORefreshTableHeaderView : UIView 
    id _delegate;
    EGOPullRefreshState _state;

    UILabel *_lastUpdatedLabel;
    UILabel *_statusLabel;
    CALayer *_arrowImage;
    UIActivityIndicatorView *_activityView;


@property(nonatomic,assign) id <EGORefreshTableHeaderDelegate> delegate;

EGORefreshTableHeaderView.m

@synthesize delegate=_delegate;

我已阅读此http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html,据我了解,它为 _delegate 创建了新名称,即代表。 (我的理解正确吗?)

但我仍然不明白他们为什么要用那些@synthesize = 指令让事情变得复杂。

【问题讨论】:

123456&c. Objective-C synthesize property name overriding的可能重复 What does @synthesize window=_window do?的可能重复 【参考方案1】:

它有多复杂,真的吗?它只是一种语法,可让您指定要用于支持您告诉编译器为其创建访问器的属性的 ivar。如果他们没有提供这个或类似的东西,那么您总是必须让您的属性名称与您的 ivar 名称相匹配,并且您可能不希望这样做。

如果您不需要以不同的方式命名您的 ivar,那么您不必费心指定 ivar 名称。事实上,您根本不必为您的属性创建 ivars……如果您不这样做,编译器会为您创建它们。

更新:从 2013 年年中开始,LLVM 默认会为属性合成访问器,因此在大多数情况下,您根本不需要指定 @synthesize。您仍然会使用它的一种情况是,当您想要使用与编译器为您生成的实例变量不同的实例变量来支持属性时。此外,支持属性的 ivar 的默认名称将是带有下划线前缀的属性名称。因此,可以通过删除以下行来简化 OP 示例中的代码:

id _delegate;

和:

@synthesize delegate=_delegate;

我已经删除了我之前反对使用下划线前缀的建议,因为它显然不同意编译器的当前时尚和默认行为。然而,据我所知,在方法名称中使用下划线前缀仍然是一种糟糕的形式。

另外,我注意到至少有一个人解释了我回答的第一行,“它有多复杂,真的吗?”作为居高临下的。我希望这只是一个人的印象——我绝对没有任何居高临下的意思,而只是试图围绕 OP 的断言来构建我的回应,即@synthesize xxx=_xxx; 指令使事情变得复杂。刚开始的时候有很多东西要吸收;希望新的“默认合成”行为能够减轻新手的负担。

【讨论】:

我是 obj-c 的新手,这不是我提到的代码,所以这对我来说很复杂。那么这里发生的只是两个名称引用相同的 obj 对吗? @synthesis newName = ivar 不会创建新的另一个 ivar,而是引用旧的对吗? Apple 的重点是方法名称不带有下划线前缀。 @art 对于@synthesize delegate = _delegate,只有一个名为_delegate 的实例变量和两个名为-delegate-setDelegate: 的访问器方法。如果是@synthesize delegate,就会有两个实例变量_delegatedelegate,以及两个名为-delegate-setDelegate:的访问器方法。 ivars 的前导下划线是完全可以接受且常用的。 google-styleguide.googlecode.com/svn/trunk/… 既然我是把第一行解释为居高临下的人,我想我不妨评论一下。我刚刚花了很长时间试图弄清楚为什么@synthesize 没有达到我的预期,这是第一个谷歌搜索结果。在与指令斗争了一段时间后,阅读“它有多复杂?”听起来确实居高临下,但我很欣赏后续行动。感谢您的详细回答。【参考方案2】:

你是对的,使用

@synthesize foobar=_foobar;

在大多数情况下有点毫无意义,但在抽象层面上,它确实允许您完全返回某个其他变量的值。如...

@synthesize foobar=fluffybunny;

让您在每次使用访问器.foobar 时获取或设置fluffybunny 的值

但是就@synthesize的复杂度而言,你更愿意写

-(void)setFoobar:(id)aobject 
    [self willSetValueForKey:"foobar"];
    id old = foobar;
    foobar = [aobject retain];
    [old release];
    [self didSetValueForKey:"foobar"];


-(id)foobar 
    [self willAccessValueForKey:"foobar"];
    id obj = [self primitiveValueForKey:@"foobar"];
    [self didAccessValueForKey:"foobar"];    
    return obj;

或者

@synthesize foobar;

这写得不是特别好,因为我忘记了如何做好它们,但是@synthesize 指令使您不必多次编写访问器。它是 Obj-C 1.0 最糟糕的地方之一。

免费代码,不要敲它。

【讨论】:

Xcode 4.4.1 forward 中的最新编译器意味着您甚至不必再使用 synthesize xyz 了。当你声明 @property xyz 时,你会得到一个隐含的声明,让你免费合成 xyz = _xyz。 @WarrenBurton 正确,但是如果您自定义实现了 xyz 的 getter 和 setter,那么您仍然必须使用 @synthasize xyz=_xyz

以上是关于Objective-c 中的 @property 和 @synthesize的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C中的@property和@synthesize用法

Objective-C中的@property和@synthesize用法

Objective-c 中的 @property 和 @synthesize

Objective-C中的@Property具体解释

知识梳理Objective-C中的@property

在 Objective-C 中覆盖 @property 声明