【问题标题】:Objective-C property attributes best practicesObjective-C 属性属性最佳实践
【发布时间】:2016-02-04 10:46:13
【问题描述】:

在多次搜索和阅读属性属性后,我仍然无法完全理解它们并产生正确使用它们的反射。

我有多个问题:

1) default 属性是什么意思?

据我了解,没有在“组”中指定属性,而是使用默认属性,因此:

@property NSString *string;

atomic,对吧?

按照这个逻辑,this article 表示 strongassign 是默认值,所以如果我有:

@property (nonatomic) NSString *string;

string 属性strong 还是assign

可用属性如何“分组”?或者正如 Xcode 所说,什么属性是互斥的?

2) 是否有任何应该遵循的通用规则?

例如,我看到一条评论说您应该将copy 用于具有可变变体的类,例如NSStringNSArray

还有一个说你应该对 C 对象使用assign

那么,总是使用:

@property (copy, nonatomic) NSString *string;
@property (assign, nonatomic) CGFloat float;

?

对于属性属性还有哪些其他标准做法?

3) 如果我使用“错误”的属性会出现什么问题?如果我只对项目中的所有属性使用nonatomic 会怎样?

【问题讨论】:

    标签: objective-c properties


    【解决方案1】:

    1a) 属性的默认属性是atomicstrong(用于对象指针)或assign(用于原始类型)和readwrite。这假设一个全 ARC 项目。

    所以@property NSString *string;@property (atomic, strong, readwrite) NSString *string; 相同。 @property int value;@property (atomic, assign, readwrite) int value; 相同。

    1b) 属性分组如下:

    • 原子/非原子
    • 强/弱/分配/复制
    • 读写/只读

    从这三个组中各选择一个。

    实际上,最新的 Objective-C 增加了对nullable/nonnull 的支持,默认为nullable

    2) 一般规则如你所说。

    • 对象指针通常应该是strong
    • 原始类型应为assign
    • weak 应在子/父引用中使用以避免引用循环。通常,父级对其子级具有强引用,而子级对其父级具有弱引用。出于同样的原因,代表通常是weak
    • copy 通常用于NSStringNSArrayNSDictionary 等,以避免在为它们分配可变变体时出现问题。这避免了值被意外更改的问题。
    • 使用copyNSMutableStringNSMutableArray 等存在一个很大的“陷阱”,因为当您将可变值分配给属性时,copy 属性会导致调用copy 方法返回原始值的非可变副本。解决方法是重写setter方法调用mutableCopy

    3) 使用错误的属性可能会产生严重的问题,具体取决于属性的需要和所使用的属性。

    • 使用assign 而不是strong 作为对象指针可能是最严重的错误。由于尝试访问已释放的对象,它可能会导致应用崩溃。

    • 在将在多个线程上同时访问的属性上使用 nonatomic 而不是 atomic 可能会导致很难发现错误和/或崩溃。

    • 使用 strong 而不是 copy 来表示 NSStringNSArray(和其他集合)可能会导致在稍后将可变变体分配给属性和其他代码时出现微妙且难以发现的错误修改这些值。

    【讨论】:

    • 很好的答案。但是,你能用更多问题的答案来更新它吗?我希望这能得到关于属性属性的最佳答案,因为当前的问题大量分布在多个现有问题上,而且大多数都是旧的和过时的。所以,对于2,换句话说,对于原始类型,你永远不需要写assign,因为它已经是默认值了,对吧?关于可变属性的好建议!
    • 好答案。解释更多可空/非空将使其完美,即使它们是新属性。
    【解决方案2】:

    @rmaddy 的回答很好。

    我会添加以下内容。

    如果您正在创建(或继承)与 Swift 互操作的类,则包含 nullablenonnull 属性属性非常很有用。如果您将它添加到头文件的任何部分,则需要为头文件的所有部分指定它(编译器警告会帮助您)。对于 Objective-C 调用者来说,从方法签名中知道什么可能是 nil 值甚至可能不是非常有用。

    另一个值得注意的属性是class。您可以向类添加属性。

    将这两项加在一起,如果你实现的是单例,

    + (MyClass *)sharedInstance;
    

    将其定义为属性非常有用:

    @property (class, nonatomic, nonnull, readonly) MyClass *sharedInstance;
    

    (在这种情况下,您需要为它添加一个支持变量,如 in this article 所述)

    这将允许您通过点符号访问共享实例。

    [MyClass.sharedInstance showMeTheMoney:YES];
    

    在 Swift 中,相当烦人的

    MyClass.sharedInstance()?.showMeTheMoney(true)
    

    变成

    MyClass.sharedInstance.showMeTheMoney(true)
    

    ‡ 对你来说可能只有 3 个字符,但它让我不会在中午爆炸。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-13
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多