Objective-C中声明@property的属性(nonatomic,copy,strong,weak)

293
有人可以详细解释一下在声明属性时,我必须使用每个属性:nonatomiccopystrongweak等的情况,并解释每个属性的作用吗?最好能提供一些例子。我正在使用ARC(自动引用计数)。

这里是答案 http://stackoverflow.com/a/32942413/1961064 - Grigori Jlavyan
这个链接解释了所有关于Objective-C属性的内容。 - Deepak Thakur
4个回答

561

非原子性(Nonatomic)

Nonatomic 不会通过 @synthesize 存取方法生成线程安全的程序。使用 atomic 会生成线程安全的存取器,因此 atomic 变量是线程安全的(可以在多个线程中访问而不会破坏数据)。

拷贝(Copy)

copy 当对象可变时才需要使用。如果您需要该对象的当前值,并且不希望该值反映其他所有者所做的任何更改,则使用此选项。完成后,您需要释放该对象,因为您正在保留其副本。

赋值(Assign)

assigncopy 相反。调用 assign 属性的 getter 方法时,它返回对实际数据的引用。通常,在具有原始类型(float、int、BOOL 等)的属性上使用此属性。

保留(Retain)

retain 当属性是指向在堆上分配的引用计数对象的指针时,就需要使用了。分配应该类似于:

NSObject* obj = [[NSObject alloc] init]; // ref counted var

@synthesize生成的setter方法在对象被复制时会增加引用计数,因此即使原始副本超出范围,底层对象也不会自动销毁。

当您使用@property并使用retain时,需要在完成后释放该对象,这将增加引用计数并占用autorelease池中的内存。

强引用(Strong)

strong是Objective-C自动引用计数(ARC)的一部分,是对retain属性的替代。在非ARC代码中,它只是retain的同义词。

这是一个学习关于iOS 5中强引用(Strong)和弱引用(Weak)的好网站。 http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1

弱引用(Weak)

weakstrong类似,但它不会使引用计数加1。它不成为该对象的所有者,只是持有一个对它的引用。如果对象的引用计数降至0,即使您仍然在此处引用它,它也将从内存中释放。

以上链接包含有关弱引用(Weak)和强引用(Strong)的良好信息。


1
如果您只是在类内部使用这个NSString,那么您甚至不需要一个属性,您可以将其作为iVar。如果您要在另一个类中使用它,我建议使用(strong,copy)。 - Ankit Srivastava
1
您缺少Assign属性。 - mskw
11
nonatomic 的意思是它不应该被多个线程同时访问。默认值是 atomic,这使它在多线程环境下是线程安全的。 - wcochran
1
令人不安的是,经过这么长时间后,nonatomic 的定义仍然是错误的,并且类似于 atomic。我想知道在过去五年中有多少人使用了它并得出了错误的印象。@wcochran所说的是正确的。nonatomic 意味着指针的访问不是原子性处理的,因此不是线程安全的。据我所知,nonatomic 的好处是它更轻量级。 - John Bushnell
1
除了@JohnBushnell的评论之外,这个答案中还有许多其他错误和不准确之处。它也已经过时了,因此有些历史性。如果你正在寻找这个问题的答案,请到其他地方寻找。 - CRD
显示剩余9条评论

45

nonatomic属性意味着@synthesize方法不会生成线程安全,但这比atomic属性更快,因为额外的检查被消除了。

strong与ARC一起使用,它基本上帮助你不必担心对象的保留计数。当你完成它时,ARC会自动释放它。使用关键字strong意味着你拥有该对象。

weak所有权意味着你不拥有它,它只是跟踪分配给它的对象,只要第二个对象被释放,它就失去了值。例如,obj.a=objectB;被使用且a具有弱属性,则其值仅在objectB保留在内存中时有效。

copy属性非常好地解释在此处

strong,weak,retain,copy,assign是相互排斥的,所以你不能在一个对象上同时使用它们...请阅读“已声明的属性”部分。

希望这能对你有所帮助...


强引用、弱引用、保留、复制和赋值是相互独立的概念。 - vinoth.kumar
"nonatomic" 只是表示没有应用排除。它并不意味着访问不是线程安全的。这是一个实现细节,"atomic" 和 "nonatomic" 无法捕获。 - bbum
@bbum,您能解释一下“无排除”和“非线程安全”的区别吗? - Ankit Srivastava
1
@AnkitSrivastava 排除是指线程A阻止线程B进入某个代码路径。如果该代码路径可以安全地从多个线程执行,则不需要排除。非线程安全意味着如果A和B同时进入该路径,可能会产生未定义的结果。这时可以使用排除来使某些内容线程安全,但线程安全并不要求独占——非并发——执行。 - bbum

16

Assign属性不是只用于iVar和值吗?那么为什么它是不安全的,为什么需要注意它是未保留的呢? - mskw

7

非常好的回答! 有一件事我想更深入地澄清,那就是nonatomic/atomic。 用户应该明白,这个属性——“原子性”仅扩展到属性的引用,而不是它的内容。 也就是说,atomic只能保证用户在读取/设置指向属性的指针时具有原子性。 例如:

@interface MyClass: NSObject
@property (atomic, strong) NSDictionary *dict;
...

在这种情况下,可以保证不同线程以原子方式读取/设置指向dict的指针。 但是,dict本身(指向的字典dict)仍然不是线程安全的,即对字典的所有读取/添加操作仍然不是线程安全的。
如果您需要线程安全的集合,则可能存在糟糕的架构(更常见)或真正的要求(更罕见)。 如果是“真正的要求”-您应该找到经过良好测试的线程安全集合组件或准备编写自己的组件并面临挑战和困难。 在后一种情况下,请查看“无锁”、“无等待”范例。乍一看似乎很高深,但与“通常的锁定”相比,可以帮助您实现出色的性能。

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