ARC-__unsafe_unretained的含义?


79

只是想确保我做对了:

  1. 我是否需要__unsafe_unretain我不拥有的物体?
  2. 如果对象是__unsafe_unretained我需要用assign@property?这是否意味着不保留该对象,而只是引用我分配给的对象?
  3. 除代理人外,我什么时候要使用它?
  4. 那是ARC东西还是以前使用过的东西?

Answers:


192

该LLVM编译器3.0中引入了四个新的所有权预选赛:__strong__autoreleasing__unsafe_unretained,和__weak。根据规范,前三个甚至在ARC之外也可用。

正如Joshua指出的,默认情况下,所有指针都隐含__strong在ARC下。这意味着,将对象分配给该指针后,只要该指针引用该对象,该对象就会保留下来。这对大多数事情来说都很好,但是正如我在此处的回答中所述,这为保留周期打开了可能性。例如,如果您有一个对象,该对象包含另一个对象作为实例变量,但是该第二个对象作为其委托具有指向第一个对象的强链接,则这两个对象将永远不会释放。

因此存在__unsafe_unretained__weak限定词。它们最常见的用途是用于委托,您可以使用weakunsafe_unretained属性(assign有效unsafe_unretained)为该委托定义一个属性,然后通过使用__weak或标记相应的实例变量来进行匹配__unsafe_unretained。这意味着委托实例变量仍将指向第一个对象,但不会导致该对象被保留,从而中断了保留周期并允许释放两个对象。

除委托外,这对于打破代码中可能形成的任何其他保留周期很有用。有用的是,泄漏工具现在包括一个“周期”视图,该视图以图形方式显示了在应用程序中发现的保留周期。

两者__unsafe_unretained和都可以__weak防止保留对象,但是方式略有不同。对于__weak,指向对象的指针将nil在其所指向的对象的释放后转换为,这是非常安全的行为。顾名思义,__unsafe_unretained即使对象被释放,它也将继续指向对象所在的内存。由于访问该已释放对象可能导致崩溃。

那你为什么要用__unsafe_unretained呢?不幸的是,__weak仅iOS 5.0和Lion作为部署目标受支持。如果您想重新定位到iOS 4.0和Snow Leopard,则必须使用__unsafe_unretained限定符,或使用Mike Ash的MAZeroingWeakRef之类的东西


2
当然,__unsafe_unretained这对于定义NSString常量的C数组等很有用,例如NSString __unsafe_unretained *myStrings = { @"Foo", @"Bar", @"Baz", nil };
jlehr

2
@shannoga-不,您必须手动将其指定__weak为限定符才能使用此类指针。您仍然可以使用__unsafe_unretained纯粹的5.0目标,它的行为不会像__weak。如果您希望某些东西可以根据目标是否支持而在两种模式之间切换,则可以使用编译器特定的定义,如我在这里建议的:stackoverflow.com/a/8594878/19679
Brad Larson

4
@jlehr-NSString *myStrings = { @"Foo", @"Bar" };无效的Objective-C语法;本身@"Foo"具有类型NSString*。也许您的意思是这样NSString *myStrings[] = { @"Foo", @"Bar" };,但是在那种情况下,我真的不明白它怎么__unsafe_unretained会特别有用。
Quuxplusone

2
@Quuxplusone在两个方面都正确-我将C数组与结构混合在一起。我应该说的是,__unsafe_unretained指向NSString常量的C结构成员可能有用,例如struct foo { __unsafe_unretained NSString * const s; int x; };
jlehr

1
也对产生影响Class。请参阅:stackoverflow.com/a/14245894/392847
Quintin Willison,

4
  1. 不,您还可以weak将您不拥有的对象用于其中。
  2. 不,您也可以unsafe_unretained在该物业上使用。
  3. 我的理解是,这些unsafe_unretained项目就像一样weak,没有释放它们所指向的项目时(以及随之而来的开销)清除它们的额外安全性。
  4. 这完全是ARC的事情。

实际上,奇怪的是,unsafe_unretained在运行时设置iVars时,它们的行为就像它们一样strong,这使我相信这unsafe_unretained只是一个编译器提示,而弱则不是。此处的更多信息:stackoverflow.com/questions/11621028/…–
理查德·罗斯三世

4

__unsafe_unretained与ARC之前对象的默认存储相同。使用ARC时,默认值现在__strong意味着您可以对其进行引用,直到引用超出范围。


1

关于__unsafe_unretained的另一个观察结果:我的设备上的应用程序发生崩溃,而不是模拟器上的iVars声明为__unsafe_unretained崩溃!是的,这是来自ARC迁移的代码中的错误,但这是我第一次注意到设备和模拟器之间的差异。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.