何时应该明确使用@synthesize?

据我所知,自XCode 4.4 @synthesize将自动生成属性访问器。 但是现在我已经阅读了关于NSUndoManager的代码NSUndoManager ,并且在代码中注意到@synthesize被明确地添加了。 喜欢:

 @interface RootViewController () @property (nonatomic, strong) NSDateFormatter *dateFormatter; @property (nonatomic, strong) NSUndoManager *undoManager; @end @implementation RootViewController //Must explicitly synthesize this @synthesize undoManager; 

我现在感到困惑…什么时候应该明确地添加@synthesize到我的代码?

有很多答案,但也是一个很大的混乱。 我会尝试下一些命令(或增加混乱,我们会看到…)

  1. 让我们停止谈论Xcode。 Xcode是一个IDE 。 铛是一个编译器 。 我们讨论的这个特性被称为属性的自动合成 ,它是由clang支持的Objective-C语言扩展 ,它是Xcode使用的默认编译器。
    为了说清楚,如果你在Xcode中切换到gcc,你将不会受益于这个特性(不pipe从Xcode版本开始)。同样,如果你使用文本编辑器并且使用命令行中的clang编译,将。

  2. 感谢自动合成,你不需要显式合成属性,因为它会被编译器自动合成

     @synthesize propertyName = _propertyName 

    但是,有一些例外:

    • 用自定义getter和setter来读写属性

      当提供getter和setter自定义实现时,该属性将不会自动合成

    • 只读属性与自定义getter

      当为readonly属性提供自定义getter实现时,将不会自动合成

    • @dynamic

      当使用@dynamic propertyName ,属性不会自动合成(非常明显,因为@dynamic@synthesize是互斥的)

    • 在@protocol中声明的属性

      当符合协议时,协议定义的任何属性将不会自动合成

    • 在类别中声明的属性

      这是@synthesize指令不被编译器自动插入的情况,但是这个属性不能手动合成。 虽然类别可以声明属性,但是它们不能被合成,因为类别不能创buildivars。 为了完整起见,我将补充说, 使用Objective-C运行时仍然可以伪造属性综合 。

    • 重写的属性 (新的铛-600.0.51,与Xcode 6一起发货,谢谢MarcSchlüpmann)

      当你重载一个超类的属性时,你必须明确地合成它

值得注意的是,合成一个属性会自动合成支持ivar,所以如果属性合成丢失,除非明确声明,否则ivar也将丢失。

除了最后三种情况之外,一般的理念是,只要手动指定一个属性的所有信息(通过实现所有访问器方法或者使用@dynamic ),编译器就会假定你想完全控制这个属性,并且会禁用它自动合成。

除了上面列出的情况之外,显式@synthesize的唯一其他用途是指定一个不同的伊娃名称。 然而,约定是重要的,所以我的build议是始终使用默认的命名。

如果你没有明确地使用@synthesize ,那么如果你编写的话,编译器会以同样的方式理解你的属性

 @synthesize undoManager=_undoManager; 

那么你将能够在你的代码中写入如下内容:

 [_undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter 

这是常见的惯例。

如果你写

 @synthesize undoManager; 

你将会拥有 :

 [undoManager doSomething]; // iVar [self.undoManager doSomethingElse]; // Use generated getter 

我个人停止使用@synthesize ,因为它不是强制性的。 对我来说,使用@synthesize的唯一理由是将iVar链接到iVar 。 如果你想为它生成特定的getter和setter。 但是在给定的代码中没有iVar ,我认为这个@synthesize是没用的。 但是现在我想新的问题是“什么时候使用iVar ?”,而我对这个问题没有任何其他的回应。

什么时候应该添加@synthesize显式给我的代码?

一般来说,如果需要的话:你可能永远不会遇到需要的情况。

有一种情况你可能觉得它很有用。

假设你正在编写一个自定义的getter和setter,但是需要一个实例variables来支持它。 (对于一个atomic属性,这和想要一个自定义setter一样简单:如果你为monatomic属性指定一个setter,编译器将写入一个getter,但不是一个atomic属性。)

考虑一下:

 @interface MyObject:NSObject @property (copy) NSString *title; @end @implementation MyObject - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end 

这是行不通的,因为_title不存在。 您已经指定了getter或setter,所以Xcode(正确)不会为它创build一个支持实例variables。

在这里输入图像说明

你有两个select让它存在。 您可以将@implementation更改为:

 @implementation MyObject { NSString *_title; } - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end 

或将其更改为:

 @implementation MyObject @synthesize title = _title; - (NSString *)title { return _title; } - (void)setTitle:(NSString *)title { _title = [title copy]; } @end 

换句话说,虽然合成是为了实际目的而不是必需的,但是当你提供一个getter / setter的时候,它可以用来定义属性支持的实例variables。 你可以决定在这里你想使用的forms。

在过去,我喜欢在@implementation {}指定实例variables,但现在我认为@synthesize路由是一个更好的select,因为它删除了冗余types,并明确地将支持variables@implementation {}到属性:

  1. 更改属性的types,并更改实例variables的types。
  2. 更改其存储限定符(例如,使其弱而不是强或弱,而不是弱)和存储限定符更改。
  3. 删除或重命名该属性,@ @synthesize将生成编译器错误。 你不会最终得到stream浪的实例variables。

* – 我知道一个有必要的情况,涉及在多个文件中跨类别分割function。 如果苹果修复这个问题,甚至已经有了,我也不会感到惊讶。

好的,当你创build一个属性…

 @property NSString *name; 

Xcode将自动合成一个iVar,就像你写了…

 @synthesize name = _name; 

这意味着你可以访问财产与…

 self.name; // or _name; 

要么工作,但只有self.name实际上使用访问器方法。

自动合成只有一次不起作用。

如果你覆盖,但setter和getter方法,那么你将需要综合iVar。

如果你只是重写setter,或者你只是重写getter,你没问题。 但是如果两者都做,编译器就不会理解它,你需要手动合成它。

作为一个经验法则。

不要制造iVar。 只要使用该属性。 不要综合它。

在协议中声明财产时,需要进行财产综合。 它不会在实现界面中自动合成。

感谢澄清。 我有一个类似的问题。

 @synthesize firstAsset, secondAsset, audioAsset; @synthesize activityView; 

所以,现在,在评论他们的时候,我经历了每一次事件

self.firstAsset看来我也可以使用firstAsset,但我发现我很想看到“ ”太频繁。

Xcode不需要显式的@synthesize声明。

如果你不写@synthesize它一样做:

 @synthesize manager = _manager; 

示例代码可能已经过时了。 他们会尽快更新。

您可以访问您的属性,如:

 [self.manager function]; 

这是苹果推荐的惯例。 我遵循它,我build议你也这样做!