一个readwrite属性和一个nonatomic assign属性有什么区别?

16

我看到了对于int、BOOL等的readwrite属性,跟nonatomic和assign一样。

我有些困惑。我知道在非原生对象上,我们通常使用nonatomic,retain。


参见:Objective-C 101(retain vs assign)@ https://dev59.com/zHM_5IYBdhLWcg3wcCnc - Ben.Vineyard
3个回答

32

以下是简要答案:

atomic vs nonatomic 主要确保从合成的getter方法中返回完整的值,以及由合成的setter方法写入完整的值(atomic是默认的)。

readwrite vs readonly 确定合成属性是否具有合成的访问器(readwrite具有setter并且是默认的,readonly则没有)。

assign vs retain vs copy 确定合成的访问器如何与Objective-C内存管理方案交互:

  • assign 是默认的,并且只执行变量赋值
  • retain 指定在分配时应将新值发送给-retain,旧值则发送-release
  • copy 指定在分配时应将新值发送到-copy,旧值则发送-release

19

在阅读了许多文章、Stack Overflow的帖子和制作演示应用程序以检查变量属性特性后,我决定将所有属性信息汇总在一起。

  1. atomic //默认值
  2. nonatomic
  3. strong=retain //默认值
  4. weak= unsafe_unretained
  5. retain
  6. assign //默认值
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite //默认值

因此,下面是详细的文章链接,在那里你可以找到上述所有属性,这肯定会对你有所帮助。非常感谢所有在这里提供最佳答案的人!!

iOS中的变量属性特性或修饰符

  1. retain = strong
    • 它被保留,旧值被释放并进行分配
    • retain指定新值应该在赋值时发送-retain,而旧值则发送-release
    • retain与strong相同
    • 苹果公司表示,如果你写retain,它将自动转换/像strong一样工作
    • 像"alloc"这样的方法包括一个隐含的"retain"

例如:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assign
    • assign 是默认值,仅执行变量赋值操作
    • assign 是一个属性特性,它告诉编译器如何合成属性的设置方法实现
    • 我会将 C 原始类型的属性使用 assign ,而将 Objective-C 对象的弱引用使用 weak。

示例:

@property (nonatomic, assign) NSString *address;

@synthesize address;
  1. 只读属性

    • 使用readonly关键字声明属性,告诉编译器不要自动生成setter方法。
    • 表示该属性是只读的。
    • 如果你指定了readonly,那么在实现块(@implementation)中只需要getter方法。如果你在实现块中使用@synthesize指令,只有getter方法会被合成。此外,如果你尝试使用点语法分配一个值,那么会得到一个编译器错误。

示例:

@property (nonatomic, readonly) NSString *name;

@synthesize name;
  1. readwrite
    • 自动生成setter和getter方法。
    • 指示属性应被视为可读/可写。
    • 这是默认属性。
    • 在 @implementation 块中需要同时实现getter和setter方法。如果在实现块中使用了 @synthesize 指令,那么getter和setter方法将会被合成。

示例:

@property (nonatomic, readwrite) NSString *name;

@synthesize name;

@jrturton 请阅读这篇文章这篇文章,如果我有错误,请指正! - swiftBoy
2
第二个链接说得很清楚。unsafe_unretained在被释放时不会将引用设置为nil,因此你会得到一个悬空指针,而weak属性在对象被释放时会被设置为nil。在iOS 4.3之前,是不支持weak的。 - jrturton

16

readwrite 表示属性具有 getter 和 setter 方法;与之相对的是 readonly。通常情况下,你只需要在一个类扩展中显式声明一个属性为 readwrite,而不是在公共接口中声明该属性为 readonly — 这样它就会被公开为只读属性,但在内部你可以进行读写操作。


2
йқһеёёеҘҪзҡ„зӯ”жЎҲгҖӮзҹҘйҒ“дҪ•ж—¶еә”иҜҘдҪҝз”ЁreadwriteжҳҜеҫҲйҮҚиҰҒзҡ„гҖӮ - rolling_codes
@Chuck,readwrite的setter和assign或retain的setter相当吗? - Vishal Singh
@VishalSingh:readwrite没有指定内存管理。您需要同时为属性列出内存管理属性。 - Chuck
明白了,谢谢。在我的测试中,我在.h文件中将一个属性声明为readonly,并在.m文件中将同一属性声明为weakreadwrite,但编译器抱怨它不能被弱引用,因为它在.h中被声明为强引用。看来只有readonly属性会被视为由__strong iVar支持。 - Vishal Singh
1
@VishalSingh:在ARC下,默认情况下,对象属性被认为是“strong”类型——这与“readonly”或其他任何东西无关,只是“strong”是对象类型的默认值。因此,如果您想将以这种方式定义的属性设置为“weak”,则头文件声明将需要是“@property(weak,readonly)”。我知道为一个变量声明内存管理看起来很奇怪,因为它应该是只读的,但这就是语言需要的。 - Chuck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接