我被我对新的桥梁修饰符ARC下变得活跃起来的一个朋友最近问。 他问我,如果我知道在特定时间和什么不同__bridge修饰符之间的区别是使用哪些。 他问我,“怎么这么他们的工作,做的时候我使用它们,我怎么使用它们,以及它们是如何工作的‘引擎盖下’”?
注:本应该是一个“分享您的知识”类型的问题,在这里我回答了这个问题我自己,但我不知道我设置正确。
我被我对新的桥梁修饰符ARC下变得活跃起来的一个朋友最近问。 他问我,如果我知道在特定时间和什么不同__bridge修饰符之间的区别是使用哪些。 他问我,“怎么这么他们的工作,做的时候我使用它们,我怎么使用它们,以及它们是如何工作的‘引擎盖下’”?
注:本应该是一个“分享您的知识”类型的问题,在这里我回答了这个问题我自己,但我不知道我设置正确。
因为我知道他们是什么,他们如何刚刚工作,我想和其他人谁想要了解ARC下__bridge改性剂可以是混乱的来源由于使用的免费桥接来实现共享用一个简单的演员。
它曾经是,如果你想,说,投你的NSArray对象到CFArrayRef用于任何目的,它可以用一个简单的铸像这样做:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (CFArrayRef) myArray;
在这种情况下,也许你有颜色一个NSArray并把它转换为CFArrayRef使用它与CoreGraphics中绘制渐变需要。
然而,随着ARC,这将不再为你工作,你会收到此错误:
那么这到底是什么意思!?!
那么事实证明,当你做这样的演员,甚至会给你ARC不喜欢它的几个“修复它”解决方案,这一切似乎都相同__bridge关键字在其中,让我们马上给他们!
根据ARC我们有3个主要__bridge修饰符:
__桥
__bridge_retained(其由CFBridgingRetain功能合作)
__bridge_transfer(其由CFBridgingRelease功能合作)
因此,我们将与__bridge开始。 它是什么? __bridge是说的只是另一种方式:“嘿编译器,只要给我该死铸造对象!”。 编译器会很乐意这样做,并返回到您自己的喜好的铸造对象!
但是,因为你想要一个“自由”铸造对象那样的, 你仍然负责释放的最初分配对象的内存。 在这种情况下,如果我这样做:
NSArray* myArray = [NSArray alloc]init];
CFArrayRef arrayRef = (__bridge CFArrayRef) myArray;
我还负责释放内存myArray的 ,因为它是原先分配的对象。 请记住,__bridge只是告诉编译器来执行转换! 而且因为我在ARC编译,我没有明确必须调用[-release]在myArray的对象上,ARC会为我做!
需要注意的是,__bridge修改两种方式都可以! (因此,免费桥接),你可以很容易地蒙上了CF对象的NS对象以相同的方式(即免费电话桥接!)像这样:
CFArrayRef arrayRef; // allocate this arrayRef and give it a value later on
//... amazing code.....
NSArray* myArray = (__bridge NSArray*)arrayRef;
但是,由于CF对象将是最初分配的对象,我必须调用CFRelease(什么);
现在让我们转移到__bridge_retained及其犯罪CFBridgingRetain()的合作伙伴。 这__bridge修饰符对传输的NS对象的所有权到CF对象明确适应(所以我们等着手动CFRelease(无论)这是由于它是一个CF类型的对象)
意思是,如果我再这样做我的老场景,但这次__bridge_retained:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (__bridge_retained) myArray;
该数组引用对象现在有一个用于由myArray的指针所拥有的记忆明确的所有权。 因为现在的CF类型有所有权,我必须用CFRelease释放它自己(无论);
那么什么样的作用呢在这一切混乱的CFBridgingRetain()函数戏? 它扮演着做,我们刚才讲到投完全相同的作用! 让我们来看看函数原型CFBridgingRetain:
CFTypeRef CFBridgingRetain(id x);
我们可以看到,它非常简单,只是简化了整个(__bridge_retained)概念为一体的功能! 我们经过“输入”的NS类型的对象流汗回CF对象! 基! 是的,我知道这是真棒! 太多的凉意采取一个坐! 是的,它也执行记忆“所有权”转让..如何真棒!
最后但绝非最不重要的,__bridge_transfer和全能CFBridgingRelease()!
__bridge_transfer作品几乎一样的__bridge_retained相反。 所述改性剂__bridge_transfer传送一个CF对象类型的一个NS对象类型的所有权。
因此,让我们指的是一直用于整个解剖它的例子:
NSArray* myArray = [NSArray alloc]initWithObjects:....]; //insert objects
CFArrayRef arrayRef = (__bridge_retained) myArray;
// at this point, arrayRef holds the ownership
// Let's add this new line to change things up a bit:
NSArray* otherArray = (__bridge_transfer NSArray*)arrayRef;
那么,这真棒小程序,我们只是写究竟做什么?
第1步:我们分配一个NSArray
步骤2:我们通过阵列的ownsership到数组引用对象
//之前,我们继续第3步,让我们在这一点上理解数组引用是所有者
第3步:我们再转移过去由数组引用所拥有回一个NSArray所有权*
因为在这个点上,otherArray指针是主人,这似乎有点自然在这一点上说,[otherArray发布]当我们做了,对不对? 嗯,这就是ARC踢,并会采取释放该数组对你的关心!
你知不知道它变冷? )CFBridgingRelease(:这__bridge修改的犯罪真棒伙伴
使它成为酷多了! CFBridgingRelease有这个函数原型:
id CFBridgingRelease(CFTypeRef x);
而我们看到,这正是我们投与__bridge_transfer这种情况发生同样的事情。 而这个功能也转移所有权的NS对象! 这真是太棒了!
使用CFBridgingXXX功能,也许可以先作一点更有意义,因为事实上,很多的Objective-C程序员仍然有NARC规则的概念:
已调用的一切:
ñ
一个地方
[R Etain的
çOPY
必须有一个平衡-释放呼叫
所以这样做:
NSArray* myArray = [[NSArray alloc]init];
// there's the A of NARC!
//(cleaned by ARC)
CFArrayRef arrayRef = CFBridgingRetain(myArray); // there's the R of NARC!!
//NSArray* other = CFBridgingRelease(arrayRef); // cleaned up by ARC
可以使学习__bridge的过程中,由于一个事实,即保持与释放匹配蒙上更容易
如果这一切仍可能会产生混淆,认为它是这样的:你是一个指向任何NS对象类型。 为了统一起见,假设你是一个NSArray指针,那现在不指向任何东西。 所以,你可以排序的想象,你作为零指针,正站在一间带灯灭。 (灯灭表示您没有指向任何东西)。
然后,后来在代码中,你的程序员决定给你分配到一个新的NSArray。 即,他/她这样说:
you = [[NSArray alloc]init];
突然,在浴室的灯光,你正站在,已经打开! 你指向一个对象! 现在,在正常的程序执行,当你使用这个对象,你松开。 所以在这种情况下,当你使用卫生间做,你关灯。
但你在,就是程序很不幸,是不是很“正常”。 程序员决定使用一些的CoreFoundation对象! 的Bleh!
他写这行代码:
CFArrayRef other = (__bridge_retained CFArrayRef) you;
所以,现在发生的事情是,另外一个人走进同时你离开浴室。 出于礼貌 ,你不关灯,因为有使用厕所另一个人,并负责将灯关闭时,他/她离开
在这种情况下,因为厕所的新主人是CF对象,程序员必须手动释放它。
但是,如果他/她是什么写这篇文章:
CFArrayRef ref = (__bridge CFArrayRef) you;
这里所发生的是,其他人只是闯进了厕所一样,你甚至不问! 太粗鲁了! 最重要的是他希望你在他后面收拾呢! 那么,你是一个绅士/淑女关灯时, 两者的完成。
但是,因为你是一个NS类型的对象,ARC来得快,清除它适合你:)
最后,如果程序员编写这样的:
you = (__bridge_transfer NSArray*)arrayRef;
这里发生的是第一种情形正好相反。 相反的,你在为别人进入的同时离开洗手间 , 你是谁,而其他人叶进入一个
同样的内存管理规则。 既然你接手“拥有”的厕所,你必须手动关灯。 而且因为你是一个NS类型的对象,ARC会为你做它...再次:)不是圆弧这样的美女!
我知道这可能起初看起来有点吓人和混乱,但只是通过它你的工作方式,读一遍,你会发现这ARC机制多么不可思议的作品!
谢谢大家的阅读! 希望这有助于:)
由于@rob mayoff和@ Krishnabhadra所有额外的帮助和建议!