据我所知,自从 XCode 4.4 @synthesize 将自动生成属性访问器。但是刚才我已经阅读了一个关于 NSUndoManager 的代码示例,并且在代码中它注意到显式添加了 @synthesize 。像:

@interface RootViewController  ()

@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;

@end

@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;

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

最佳答案

有很多答案,但也有很大的困惑。我会试着安排一些订单(或增加困惑,我们会看到......)

  • 让我们停止谈论 Xcode。 Xcode 是一个 IDE 。 clang 是一个 编译器 。我们正在讨论的这个特性称为属性的自动合成,它是一个 Objective-C language extension supported by clang ,这是 Xcode 使用的默认编译器。
    明确地说,如果您在 Xcode 中切换到 gcc,您将无法从该功能中受益(无论是 Xcode 版本。)同样,如果您使用文本编辑器并从命令行使用 clang 进行编译,您将将要。
  • 多亏了自动合成,你不需要显式合成属性,因为它会被编译器自动合成为
    @synthesize propertyName = _propertyName
    

    但是,存在一些异常(exception)情况:
  • 具有自定义 getter 和 setter 的读写属性

    当同时提供 一个 getter 和 setter 自定义实现时,该属性不会自动合成
  • 只读属性,自定义 getter

    为只读属性提供自定义 getter 实现时,不会自动合成
  • @动态

    使用 @dynamic propertyName 时,该属性不会自动合成(很明显,因为 @dynamic@synthesize 是互斥的)
  • 在@protocol 中声明的属性

    符合协议(protocol)时,协议(protocol)定义的任何属性都不会自动合成
  • 在类别中声明的属性

    在这种情况下,编译器不会自动插入 @synthesize 指令,但也无法手动合成此属性。虽然类别可以声明属性,但它们根本无法合成,因为类别不能创建 ivars。为了完整起见,我将补充说它仍然是可能的 to fake the property synthesis using the Objective-C runtime
  • 覆盖的属性 (自 clang-600.0.51 以来是新的,随 Xcode 6 一起提供,感谢 Marc Schlüpmann)

    当您覆盖父类(super class)的属性时,您必须显式合成它

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

    除了最后三种情况,一般的理念是,每当您手动指定有关属性的所有信息(通过实现所有访问器方法或使用 @dynamic )时,编译器都会假设您希望完全控制该属性,并且它将禁用自动合成在上面。

    除了上面列出的情况外,显式 @synthesize 的唯一其他用途是指定不同的 ivar 名称。但是约定很重要,所以我的建议是始终使用默认命名。

    关于objective-c - 我什么时候应该明确使用@synthesize?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19784454/

    10-13 09:13