Core Foundation框架

转载自:http://blog.csdn.net/weiwangchao_/article/details/7744972

Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能。下面列举该框架支持进行管理的数据以及可提供的服务:

  • 群体数据类型 (数组、集合等)

  • 程序包

  • 字符串管理

  • 日期和时间管理

  • 原始数据块管理

  • 偏好管理

  • URL及数据流操作

  • 线程和RunLoop

  • 端口和soket通讯

Core Foundation框架和Foundation框架紧密相关,它们为相同功能提供接口,但Foundation框架提供Objective-C接口。如果您将Foundation对象和Core Foundation类型掺杂使用,则可利用两个框架之间的 “toll-free bridging”。所谓的Toll-free bridging是说您可以在某个框架的方法或函数同时使用Core Foundatio和Foundation 框架中的某些类型。很多数据类型支持这一特性,其中包括群体和字符串数据类型。每个框架的类和类型描述都会对某个对象是否为 toll-free bridged,应和什么对象桥接进行说明。

如需进一步信息,请阅读Core Foundation 框架参考


自 Xcode4.2 开始导入ARC机制后,为了支持对象间的转型,Apple又增加了许多转型用的关键字。这一讲我们就来了解其用法,以及产生的理由。

引子

我们先来看一下ARC无效的时候,我们写id类型转void*类型的写法:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[[</span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSObject</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> alloc</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">]</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> init</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> obj</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li></ol>

反过来,当把void*对象变回id类型时,只是简单地如下来写,

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> p</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">obj release</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li></ol>

但是上面的代码在ARC有效时,就有了下面的错误:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    error</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">:</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">implicit</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> conversion of an </span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">Objective</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">-</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">C pointer</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">        to </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">’</span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">is</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> disallowed </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">with</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> ARC</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">        </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> obj</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">                  </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">^</span></li><li class="L4" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L5" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    error</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">:</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">implicit</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> conversion of a non</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">-</span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">Objective</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">-</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">C pointer</span></li><li class="L6" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">        type </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">’</span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> to </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">is</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> disallowed </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">with</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> ARC</span></li><li class="L7" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">        id o </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> p</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L8" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">                </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">^</span></li></ol>

__bridge

为了解决这一问题,我们使用 __bridge 关键字来实现id类型与void*类型的相互转换。看下面的例子。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[[</span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSObject</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> alloc</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">]</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> init</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">obj</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L4" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id o </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li></ol>

将Objective-C的对象类型用 __bridge 转换为 void* 类型和使用 __unsafe_unretained 关键字修饰的变量是一样的。被代入对象的所有者需要明确对象生命周期的管理,不要出现异常访问的问题。

除过 __bridge 以外,还有两个 __bridge 相关的类型转换关键字:

  • __bridge_retained
  • __bridge_transfer

接下来,我们将看看这两个关键字的区别。

__bridge_retained

先来看使用 __bridge_retained 关键字的例子程序:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[[</span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSObject</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> alloc</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">]</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> init</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_retained </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">obj</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li></ol>

从名字上我们应该能理解其意义:类型被转换时,其对象的所有权也将被变换后变量所持有。如果不是ARC代码,类似下面的实现:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[[</span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSObject</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> alloc</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">]</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> init</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> obj</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p retain</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li></ol>

可以用一个实际的例子验证,对象所有权是否被持有。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="lit" style="color:#06666;border: 0px; margin: 0px; padding: 0px;">0</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">{</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[[</span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSObject</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> alloc</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">]</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> init</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li><li class="L4" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    p </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_retained </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">void</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">obj</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L5" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">}</span></li><li class="L6" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L7" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSLog</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(@</span><span class="str" style="color:#0880;border: 0px; margin: 0px; padding: 0px;">"class=%@"</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">,</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p </span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">class</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">]);</span></li></ol>

出了大括号的范围后,p 仍然指向一个有效的实体。说明他拥有该对象的所有权,该对象没有因为出其定义范围而被销毁。

__bridge_transfer

相反,当想把本来拥有对象所有权的变量,在类型转换后,让其释放原先所有权的时候,需要使用 __bridge_transfer 关键字。文字有点绕口,我们还是来看一段代码吧。

如果ARC无效的时候,我们可能需要写下面的代码。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="com" style="color:#8800;border: 0px; margin: 0px; padding: 0px;">// p 变量原先持有对象的所有权</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">obj retain</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">[(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p release</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">];</span></li></ol>

那么ARC有效后,我们可以用下面的代码来替换:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="com" style="color:#8800;border: 0px; margin: 0px; padding: 0px;">// p 变量原先持有对象的所有权</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id obj </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_transfer id</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">p</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li></ol>

可以看出来,__bridge_retained 是编译器替我们做了 retain 操作,而 __bridge_transfer 是替我们做了 release1

Toll-Free bridged

在iOS世界,主要有两种对象:Objective-C 对象和 Core Foundation 对象0。Core Foundation 对象主要是有C语言实现的 Core Foundation Framework 的对象,其中也有对象引用计数的概念,只是不是 Cocoa Framework::Foundation Framework 的 retain/release,而是自身的 CFRetain/CFRelease 接口。

这两种对象间可以互相转换和操作,不使用ARC的时候,单纯的用C原因的类型转换,不需要消耗CPU的资源,所以叫做 Toll-Free bridged。比如 NSArray和CFArrayRef, NSString和CFStringRef,他们虽然属于不同的 Framework,但是具有相同的对象结构,所以可以用标准C的类型转换。

比如不使用ARC时,我们用下面的代码:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">[</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> stringWithFormat</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">:...];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> cfString </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">;</span></li></ol>

同样,Core Foundation类型向Objective-C类型转换时,也是简单地用标准C的类型转换即可。

但是在ARC有效的情况下,将出现类似下面的编译错误:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">Cast</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> of </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">Objective</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">-</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">C pointer type </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">‘</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> to C pointer type </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">‘</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">aka </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">‘</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">const</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">struct</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> __CFString </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*’)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> requires a bridged cast</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">Use</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> __bridge to convert directly </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">no</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> change </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">in</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> ownership</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">Use</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> __bridge_retained to make an ARC </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">object</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> available </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">as</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> a </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">+</span><span class="lit" style="border: 0px; margin: 0px; padding: 0px;">1</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">‘</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">’</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">aka </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">‘</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">const</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">struct</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> __CFString </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*’)</span></li></ol>

错误中已经提示了我们需要怎样做:用 __bridge 或者 __bridge_retained 来转型,其差别就是变更对象的所有权。

正因为Objective-C是ARC管理的对象,而Core Foundation不是ARC管理的对象,所以才要特意这样转换,这与id类型向void*转换是一个概念。也就是说,当这两种类型(有ARC管理,没有ARC管理)在转换时,需要告诉编译器怎样处理对象的所有权。

上面的例子,使用 __bridge/__bridge_retained 后的代码如下:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">[</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> stringWithFormat</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">:...];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> cfString </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">;</span></li></ol>

只是单纯地执行了类型转换,没有进行所有权的转移,也就是说,当string对象被释放的时候,cfString也不能被使用了。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">[</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> stringWithFormat</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">:...];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> cfString </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_retained </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">...</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFRelease</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">cfString</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">);</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="com" style="border: 0px; margin: 0px; padding: 0px;">// 由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己release</span></li></ol>

使用 __bridge_retained 可以通过转换目标处(cfString)的 retain 处理,来使所有权转移。即使 string 变量被释放,cfString 还是可以使用具体的对象。只是有一点,由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己release。

实际上,Core Foundation 内部,为了实现Core Foundation对象类型与Objective-C对象类型的相互转换,提供了下面的函数。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFTypeRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">  </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFBridgingRetain</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id  X</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">  </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">{</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">return</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">  </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_retained  </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFTypeRef</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">X</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">}</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L4" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">id  </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFBridgingRelease</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFTypeRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">  X</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">  </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">{</span></li><li class="L5" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">    </span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">return</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">  </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_transfer  id</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">X</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L6" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">}</span></li></ol>

所以,可以用 CFBridgingRetain 替代 __bridge_retained 关键字:

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">*</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">[</span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> stringWithFormat</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">:...];</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> cfString </span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFBridgingRetain</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="kwd" style="border: 0px; margin: 0px; padding: 0px;">string</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">);</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">...</span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; margin: 0px; padding: 0px;">CFRelease</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">cfString</span><span class="pun" style="border: 0px; margin: 0px; padding: 0px;">);</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="com" style="border: 0px; margin: 0px; padding: 0px;">// 由于Core Foundation不在ARC管理范围内,所以需要主动release。</span></li></ol>
__bridge_transfer

所有权被转移的同时,被转换变量将失去对象的所有权。当Core Foundation对象类型向Objective-C对象类型转换的时候,会经常用到 __bridge_transfer 关键字。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> cfString </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">CFStringCreate</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">...();</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">string</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">__bridge_transfer </span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*)</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">cfString</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">;</span></li><li class="L2" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span></li><li class="L3" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="com" style="color:#8800;border: 0px; margin: 0px; padding: 0px;">// CFRelease(cfString); 因为已经用 __bridge_transfer 转移了对象的所有权,所以不需要调用 release</span></li></ol>

同样,我们可以使用 CFBridgingRelease() 来代替 __bridge_transfer 关键字。

<ol class="linenums" style="border: 0px; margin: 0px; padding: 0px 0px 0px 26px;"><li value="1" class="L0" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal;"><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">CFStringRef</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> cfString </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">CFStringCreate</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">...();</span></li><li class="L1" style="border: 0px; margin: 0px 0px 0px 20px; padding: 0px; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">NSString</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">*</span><span class="kwd" style="color:#0088;border: 0px; margin: 0px; padding: 0px;">string</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">=</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;"> </span><span class="typ" style="color:#66066;border: 0px; margin: 0px; padding: 0px;">CFBridgingRelease</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">(</span><span class="pln" style="border: 0px; margin: 0px; padding: 0px;">cfString</span><span class="pun" style="color:#66660;border: 0px; margin: 0px; padding: 0px;">);</span></li></ol>

总结

由上面的学习我们了解到 ARC 中类型转换的用法,那么我们实际使用中按照怎样的原则或者方法来区分使用呢,下面我总结了几点关键要素。

  • 明确被转换类型是否是 ARC 管理的对象
    • Core Foundation 对象类型不在 ARC 管理范畴内
    • Cocoa Framework::Foundation 对象类型(即一般使用到的Objectie-C对象类型)在 ARC 的管理范畴内
  • 如果不在 ARC 管理范畴内的对象,那么要清楚 release 的责任应该是谁
  • 各种对象的生命周期是怎样的

1. 声明 id obj 的时候,其实是缺省的申明了一个 __strong 修饰的变量,所以编译器自动地加入了 retain 的处理,所以说 __bridge_transfer 关键字只为我们做了 release 处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值