前几天查阅别人代码,看到了
__unsafe_unretained
修饰符,因为很少遇见,所以立即Google,发现StackOverFlow里有一个很不错的解释,所以翻译过来给大家一起看看。
一、问题
问题翻译
仅仅是为了确认我理解的对:
1、我需要用__unsafe_unretained
来修饰不属于我的参数么?
2、如果一个参数是被__unsafe_unretained
修饰,我需要在@property
里面用assign
修饰么?那是否意味着这个对象不被保留,只是引用了我指定的对象?
3、除了代理之外,我什么时候需要用到它?
4、它是一个ARC的东西,还是我要在它之前用?
二、回答
回答翻译
LLVM 3.0编译器提供了四中私有的标示符:__strong
、__autoreleasing
、__unsafe_unretained
和__weak
。前三个甚至在ARC之外也是有用的,正如说明书中所说。
正如Joshua所说的,默认在ARC情况下所有的指针都指向__strong
。这意味着当一个对象分配给了那个指针,只要指向它,它就是被持有的。这样大部分情况下都是没问题的,正如我回答的这个问题,这样有一定可能性会导致循环引用。比如,如果有一个包含了其他对象作为实例变量的对象,但第二对象作为第一个对象的代理具有强关联,这两个对象将永远不会被释放。
就是因为这个原因导致__unsafe_unretained
和__weak
的存在。他们最通常是用在代理上,在这里你会为那个代理定义一个有weak
或者unsafe_unretained
参数的属性(assign
和unsafe_unretained
一样的作用),然后通过weak
或者__unsafe_unretained
标记相应的实例变量来匹配。这就意味着那个代理实例变量仍然指向第一个对象,但是它不会导致那个参数被持有,从而打破循环引用并允许两个参数被释放。
除了代理之外,这个也对打破在你的代码里形成的任何循环引用都有用处。有帮助的是,Leaks instrument现在包括一个Cycles界面,它会用图形的方法展示在你的应用里发现的循环引用。
但是在细微不同的方式下,__unsafe_unretained
和__weak
都防止了参数的持有。对于__weak
,指针的对象在它指向的对象释放的时候回转换为nil,这是一种特别安全的行为。就像他的名字表达那样,__unsafe_unretained
会继续指向对象存在的那个内存,即使是在它已经销毁之后。这会导致因为访问那个已释放对象引起的崩溃。
那么为什么你还要使用__unsafe_unretained
?不幸的是,__weak
只支持iOS 5.0和OS X Mountain Lion作为部署版本。如果你想部署回iOS 4.0和OS X Snow Leopark,你就不得不用__unsafe_unretained
标识符,或者用一些其他东西,就像Mike Ash的MAZeroingWeakRef
本篇翻译是我第一次翻译英文技术问答,翻译中一定会出现翻译不得当的地方,欢迎各位同行朋友予以指正交流,收到反馈之后,我一定第一时间改正错误。