CFStringRef 到 nsstring nsdataARC泄漏.为什么

ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系
总结于 IOS Tuturial 中 ARC两章,详细在dropbox pdf
Objective-C
Foundation 对象之间进行转换时,就需要使用
今天的多数应用很少需要使用
Foundation,大多数工作都可以直接使 用
Objective-C
类来完成。但是某些底层
Core Graphics 和
Text, 都基于
Foundation,而且不太可能会有 Objective-C 的版本。幸运的是,
的设计使得这两种类型的对象非常容易转换。
CFStringRef
就可以同等对待,在任何地方都可以互换使
用,背后的设计就是 toll-free
bridging。在 ARC 之前,只需要使用一个简单
的强制类型转换即可:
当然,alloc 分配了
对象,你需要在使用完之后进行释放,注意是
释放转换后的 CFStringRef
对象:CFRelease(s1);
Foundation 到
Objective-C
的方向也类似:
现在我们使用了
ARC,情况变得不一样!以下代码在手动内存管理中是完全
合法的,但在
中却存在问题:-
(NSString *)escape:(NSString *)text{
CFStringRef s1 =
(CFStringRef) [[NSString alloc]
<img ALT="page21image8008" WIDTH="282.840000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
initWithFormat:@"Hello,
%@!", name];
<img ALT="page21image8920" WIDTH="207.840000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
CFStringRef s2 =
CFStringCreateWithCString(kCFAllocatorDefault, bytes,
<img ALT="page21image10184" WIDTH="409.800000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
kCFStringEncodingMacRoman);
<img ALT="page21image11016" WIDTH="155.880000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
NSString *s3 =
(NSString *)s2;
<img ALT="page21image12008" WIDTH="173.160000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
release the object when you're done
<img ALT="page21image13080" WIDTH="219.360000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
[s3 release];
<img ALT="page21image13952" WIDTH="75.000000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
<img ALT="page21image14496" WIDTH="5.760000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
return [(NSString
*)CFURLCreateStringByAddingPercentEscapes(
(CFStringRef)text,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
// 这里不需要
casts,因为这是一个常量,不需要释放!
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncodin
autorelease];
首先需要移除
autorelease
调用。然后编译器还会报两个类型转换错误:
C pointer type 'CFStringRef' to Objective-C pointer type 'NSString
*' requires a bridged cast
Objective-C pointer type 'NSString *' to C pointer type
'CFStringRef' requires a bridged cast
错误分别来自以下两行代码:
编译器必须知道由谁来负责释放转换后的对象,如果你把一个
Foundation 对象来使用,则
将不再负责释放该对象。但你必须明确
地告诉 ARC
你的这个意图,编译器没办法自己做主。同样如果你创建一个
Foundation 对象并把它转换为
对象,你也必须告诉
占据对象的所
有权,并在适当的时候释放该对象。这就是所谓的 bridging
CFURLCreateStringByAddingPercentEscapes()函数的参数需要两个
CFStringRef 对象,其中常量
可以直接转换,因为不需要进行对象释
放;但是 text
参数不一样,它是传递进来的一个
对象。而函数参数
和局部变量一样,都是 strong
指针,这种对象在函数入口处会被
retain,并且
对象会持续存在直到指针被销毁(这里也就是函数返回时)。
参数,我们希望
保持这个变量的所有权,同时又希望临时将
它当作 CFStringRef
对象来使用。这种情况下可以使用__bridge
说明符,它告 诉 ARC
不要更改对象的所有权,按普通规则释放该对象即可。
多数情况下,Objective-C
对象和 Core
Foundation 对象之间互相转换时,
我们都应该使用__bridge。但是有时候我们确实需要给予 ARC
某个对象的所有权,
或者解除 ARC
对某个对象的所有权。这种情况下我们就需要使用另外两种
__bridge_transfer:给予
ARC 所有权
__bridge_retained:解除
ARC 所有权
在上面代码中,"return
*)CFURLCreateStringByAddingPercentEscapes",编译器弹出的修复提示有两个:
<img ALT="page23image1720" WIDTH="450.922051" HEIGHT="160.944770"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
两个解决办法:__bridge
和 __bridge_transfer,正确的选择应该
__bridge_transfer。
CFURLCreateStringByAddingPercentEscapes()
函数创建了一个新 的
CFStringRef
对象,当然我们要的是
对象,因此我们使用了强制转
换。实际上我们真正想要做的是:
CFURLCreateStringByAddingPercentEscapes
出,函数会返回一个 retain
过的对象。某个人需要负责在适当的时候释放该对
象,如果我们不把这个对象返回为 NSString,则通常我们需要自己调用:
只能作用于
Objective-C
对象,不能释放
Foundation 对象。
因此这里你仍然需要调用 CFRelease()来释放该对象。
这里我们的真实意图是:转换新创建的
CFStringRef
并且当我们不再需要使用这个 NSString
对象时,ARC
能够适当地释放它。
因此我们使用 __bridge_transfer告诉ARC:"嘿!ARC,这个CFStringRef
对象现在是一个
对象了,我希望你来销毁它,我这里就不调用
CFRelease()来释放它了"。
如果我们使用
__bridge,就会导致内存泄漏。ARC并不知道自己应该在使
用完对象之后释放该对象,也没有人调用
CFRelease()。结果这个对象就会永远
保留在内存中。因此选择正确的
说明符是至关重要的。
为了代码更加可读和容易理解,iOS
还提供了一个辅助函数: CFBridgingRelease()。函数所做事情和
__bridge_transfer 强制转换完全一
样,但更加简洁和清晰。CFBridgingRelease() 函数定义为内联函数,因此不会
导致额外的开销。函数之所以命名为 CFBridgingRelease(),是因为一般你会在
CFRelease()释放对象的地方,调用
CFBridgingRelease()来传递对象 的所有权。
因此最后我们的代码如下:
- (NSString *)escape:(NSString *)text
另一个常见的需要
CFBridgingRelease
AddressBook
framework:
- (NSString *)firstName
只要你调用命名为
Copy, Retain 的
Foundation 函数,你都 需要使用
CFBridgingRelease()安全地将值传递给ARC。
__bridge_retained
则正好相反,假设你有一个
对象,并且要将
它传递给某个 Core Foundation
API,该函数希望接收这个 string 对象的所有
权。这时候你就不希望 ARC
也去释放该对象,否则就会对同一对象释放两次,而
且必将导致应用崩溃!换句话说,使用 __bridge_retained
将对象的所有权给 予
Foundation,而 ARC 不再负责释放该对象。
如下面例子所示:
<img ALT="page24image9120" WIDTH="5.760000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
CFStringRef)text,
CFSTR("!*'();:@&=+$,/?%#[]"),
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncodin
<img ALT="page24image15512" WIDTH="5.760000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
<img ALT="page24image16056" WIDTH="5.760000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
CFBridgingRelease(ABRecordCopyCompositeName(...));
<img ALT="page24image17200" WIDTH="5.760000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
NSString *s1 =
[[NSString alloc] initWithFormat:@"Hello, %@!", name];
<img ALT="page24image18312" WIDTH="398.280000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
CFStringRef s2 =
(__bridge_retained CFStringRef)s1;
<img ALT="page24image19304" WIDTH="294.360000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
// do something with s2
<img ALT="page24image20296" WIDTH="132.720000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
<img ALT="page24image21248" WIDTH="46.200000" HEIGHT="12.360000"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />
CFRelease(s2);
<img ALT="page24image22080" WIDTH="80.880000" HEIGHT="12.360000" STYLE="font-family: symbolMT; font-size: 10"
TITLE="ARC中__bridge,&__bridge__transfer,&__bridge_retained&关系" />&
(__bridge_retained
CFStringRef) 转换完成,ARC 就不再负责释放该
对象。如果你在这里使用 __bridge,应用就很可能会崩溃。ARC
Foundation 正在使用该对象时,释放掉它。
同样__bridge_retained
也有一个辅助函数:CFBridgingRetain()。从名字 就可以看出,这个函数会让 Core
Foundation 执行
retain,实际如下:
现在你应该明白了,上面例子的
CFRelease()是和
CFBridgingRetain()对应 的。你应该很少需要使用__bridge_retained
或 CFBridgingRetain()。
转换不仅仅局限于
Foundation 对象,某些
* 指针作为参数,允许你传递任何东西的引用:Objective-C
对象、Core Foundation
对象、malloc()内存缓冲区等等。void
*表示这是一个指针,但实际的数据类型
可以是任何东西!
Objective-C
*互相转换,你也需要使用__bridge 转换, 如下:
delegate 方法中,你再将对象强制转回来:
CFBridgingRelease(),从
Core Foundation 传递所有权给
Objective-C;
CFBridgingRetain(),从
Objective-C 传递所有权给
使用__brideg,表示临时使用某种类型,不改变对象的所有权。&
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。[ios]prepareForSegue 不会执行
我演示图板 (xcode5) 与嵌入式的导航控制器 (导航控制器点到我的主视图控制器)。
我创建了一个词名称到一个新的视图控制器,希望通过我的代码可以打开。
[[self navigationController] performSegueWithIdentifier:@"segueTo" sender:self];
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(@"Segue");
视图控制器做开放但永远 prepareForSegue 不会运行,为什么呢?
[self performSegueWithIdentifier:@"segueTo" sender:self];
但我就说它找不到词名称一个运行时错误。
解决方法 1:
捡你尝试执行必须从链接 viewcontroller1 (嵌入导航控制器) 到 newviewcontroller 。在演示图板,请确保您已命名为"segueTo"作为连接起来。然后在 viewcontroller1 ,调用:
[self performSegueWithIdentifier:@"segueTo" sender:self];
[[self navigationController] performSegueWithIdentifier:@"segueTo" sender:self];
这应该可以解决您的问题。Managing Toll-Free Bridging
在cocoa&application的应用中,我们有时会使用Core&Foundation(CF),我们经常会在Objective-C和CF之间进行转化。系统使用arc的状态下,编译器不能自动管理CF的内存,这时候你必须使用CFRetain和CFRelease来进行CF的内存的管理。
具体的CF内存管理规则见:&
在OC和FC之间进行转化的时候,主要是对象的归属问题。共有两种方式:
1、使用宏,可以标识归属者从OC到CF,还是从CF到OC。
NS_INLINE&CFTypeRef&CFBridgingRetain(id&X)&{&&&&&
&&&&return&(__bridge_retain&CFTypeRef)X;&&&&&&
NS_INLINE&id&CFBridgingRelease(CFTypeRef&X)&{&&&&&&
&&&&return&(__bridge_transfer&id)X;&&&&&&
2、使用转化符,如:__bridge,__bridge_transfer,__bridge_retained
id&my_&&&&&
CFStringRef&my_&&&&&&
NSString&&&*a&=&(__bridge&NSString*)my_&&&&&//&Noop&cast.&&&&&&
CFStringRef&b&=&(__bridge&CFStringRef)my_&&&&&&//&Noop&cast.&&&&&&
NSString&&&*c&=&(__bridge_transfer&NSString*)my_&//&-1&on&the&CFRef&&&&&&
CFStringRef&d&=&(__bridge_retained&CFStringRef)my_&&//&returned&CFRef&is&&#43;1
下面以详细的例子来介绍一下OC和CF在arc下内存管理的详细写法.下面以CFURLCreateStringByAddingPercentEscapes()函数为例说一下在ARC下的写法和非ARC下的写法。
非ARC模式下的写法:
#pragma&mark&–&View&lifecycle&&&&&
-&(void)viewDidLoad&&&&&&
&&&&[super&viewDidLoad];&&&&&&
&&&&NSLog(@&=%@&,&[self&escape:@&wangjun&]);&&&&&&
-(NSString&*)escape:(NSString&*)text&&&&&&
&&&&return&(NSString&*)CFURLCreateStringByAddingPercentEscapes(&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NULL,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(__bridge&CFStringRef)text,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NULL,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFSTR(&!*’();:@&=&#43;$,/?%#[]&),&CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));;&&&&&&
使用instruments检测,没有内存泄漏。
下面把上面工程改为arc模式。
可以看到xcode自动把上面函数转化为:
#pragma&mark&–&View&lifecycle&&&&&
-&(void)viewDidLoad&&&&&&
&&&&[super&viewDidLoad];&&&&&&
&&&&NSLog(@&=%@&,&[self&escape:@&wangjun&]);&&&&&&
-(NSString&*)escape:(NSString&*)text&&&&&&
&&&&return&(__bridge_transferNSString&*)CFURLCreateStringByAddingPercentEscapes(&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NULL,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(__bridge&CFStringRef)text,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NULL,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFSTR(&!*’();:@&=&#43;$,/?%#[]&),&CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));;&&&&&&
在arc中,CF和OC之间的转化桥梁是&__bridge,有两种方式:
__bridge_transfer&&ARC接管管理内存
__bridge_retained&&ARC释放内存管理
上面的方法是从CF转化为OC&NSString对象,使用的__bridge_transfer&,对象所有者发生转变,由CF到OC,最后由ARC接管内存管理。运行上面的代码,用instruments检测,是没有内存泄漏的。
上面代码等同于:
-&(NSString&*)escape:(NSString&*)text&&&&&
return&CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(&&&&&&
NULL,&&&&&&
(__bridge&CFStringRef)text,&&&&&&
NULL,&&&&&&
CFSTR(&!*’();:@&=&#43;$,/?%#[]&),&CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)));}
如果将上述代码改为:
-(NSString&*)escape:(NSString&*)text&&&&&
&&&&return&(__bridgeNSString&*)CFURLCreateStringByAddingPercentEscapes(&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NULL,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(__bridge&CFStringRef)text,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NULL,&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CFSTR(&!*’();:@&=&#43;$,/?%#[]&),&CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));;&&&&&&
编译也会成功,但是这时候用instruments检测,可以发现内存泄漏:
由于CF转化完OC,没有自己释放内存,同时也没有把内存管理交给ARC,所以出现内存泄漏。由于__bridge只是同一个对象的引用,内存的所有权没有发生变化。
下面在说一下oc到CF的转化,需要把OC的内存管理权释放掉。
NSString&*s1&=&[[NSString&alloc]&initWithFormat:@&Hello,&%@!&,&name];&&&&&
CFStringRef&s2&=&(__bridge_retained&CFStringRef)s1;&&&&&&
//&do&something&with&s2&//&.&.&.&&&&&&
CFRelease(s2);
最后由CF进行内存释放。
上面代码等同于:
CFStringRef&s2&=&CFBridgingRetain(s1);&&&&&
//&.&.&.&&&&&&
CFRelease(s2);
下面总结一下我们使用ARC情况下。oc和CF互相转化的原则:
CF转化为OC时,并且对象的所有者发生改变,则使用CFBridgingRelease()或__bridge_transfer&。
OC转化为CF时,并且对象的所有者发生改变,则使用CFBridgingRetain()或__bridge_retained
当一个类型转化到另一种类型时,但是对象所有者没有发生改变,则使用__bridge.
ARC对象和非ARC对象对于初学者,首先需要分清楚两种不同种类的对象:
Objective-C 对象,它继承自NSObject的所有对象。在ARC中,我们可以理解为ARC对象。Core Foundation 对象,它是由C的struct定义的各种对象,主要来自于CoreFoundation框架(如CFArray或者CFMutableDictionaryRef类型),或者其它采用CoreFoundation命名规范的框架,如Core Graphics(如,CGColorSpaceRef 和CGGradientRef)。我们可以理解为Non-ARC 对象。ARC 编译器目前不会自动管理CoreFoundation 对象的生命周期。因此程序员需要调用CFRetain 和CFRelease来手动管理这些对象。& 在 非ARC编译器时代,Objective C对象和Core Foundation对象之间可以无缝衔接(Toll-FreeBridging),他们可以采用类型转化(cast)自由互相转化。但在ARC编译器中,ObjectiveC对象的生命周期由编译器负责,因此在这种无缝转化中,程序员需要使用新的类型转化关键字或者类&#20284;CF的宏,让编译器知道对象的所有者是编译器还是程序员。这些新的关键字是:·&&&&&&&&__bridge (定义在objc/runtime.h)在ARC对象和Non-ARC对象之间,简单得进行指针&#20540;得传递,没有所有权的转移。·&&&&&&&&__bridge_transfer(CFBridgingRelease (定义在NSObject.h))用于转换Non-ARC指针到ARC指针,并且将对象所有权转移给ARC,这样,ARC将释放该对象。·&&&&&&&&__bridge_retained(CFBridgingRetain)用于转化ARC指针到Non-ARC指针,并转移所有权给程序员。 程序员需要以后调用CFRelease或以其他方式释放对象的所有权。如何使用这些特殊注释关键字ARC只能管理Objective-C的类型。CoreFoundation类型仍然必须由程序员来手动管理。有关所有权,因为有歧义,ARC禁止Objective-C对象的指针和其他类型,包括的CoreFoundation对象的指针的指针之间的标准转化。在Non-ARC编译中,下面的代码是非常典型的手动内存管理下,&&&&OBJ& = &(ID )CFDictionaryGetValue的(cfDict , key);在ARC编译中,为了使其能重新编译,你必须使用上面的特殊注释关键字(__bridge,__bridge_retained,__bridge_transfer),向编译器说明对象的所有权。。__bridge最简单的理解是__bridge。这是一个没有所有权后果的直接转换。ARC接收&#20540;,然后正常管理。这就是我们想为上述:&&& ID&OBJ&= &(__bridge& ID )CFDictionaryGetValue, (cfDict , key);其他两个强转注释涉及所有权的转让。他们可以帮助缓解来回ARC- non-ARC类型转化的痛苦。让我们来看看。下面是一个在NonARC,返回的对象需要被释放的情况下使用桥接的例子。&&&NSString *value = (NSString *)CFPreferencesCopyAppValue(CFSTR(&someKey&),CFSTR(&pany.someapp&));&&& [self useValue: value];&&&[value release];如果在ARC中, 我们使用&__bridge,删除release,其它代码不作任何修改,下面的代码会产生内存泄漏:&&&NSString *value = (__bridge NSString *)CFPreferencesCopyAppValue(CFSTR(&someKey&),CFSTR(&pany.someapp&));&&&[self useValue: value];在这段代码Copy的对象需要被释放。ARC将retain初始化时value,然后当value不再使用的时候释放value。因为没有平衡原始的copy 对象,该对象被泄漏了。我们可以用下面的代码解决这一问题:&&&CFStringRef valueCF = CFPreferencesCopyAppValue(CFSTR(&someKey&),CFSTR(&pany.someapp&));&&&NSString *value = (__bridge NSString *)valueCF;& &&CFRelease(valueCF);&&&&[self useValue:value];这是相当冗长,虽然。由于无缝衔接的关键就是要尽可能让程序员不要太痛苦的处理这种代码,整个ARC就是消除需要编写内存管理代码。如果可以变得更简单,那就再好不过了。__bridge_transfer__bridge_transfer注解解决这个问题。而不是简单地移动到ARC的指针&#20540;,它转移了指针的&#20540;和对象的所有权。当__bridge_transfer在强转中使用时,它告诉ARC这个对象已经保留,ARC并不需要再保留它。由于ARC拥有所有权,当这个对象不再需要的时候,它仍然会释放它。最终的比较清爽的代码将是:&&& NSString&*value&=&(__bridge_transfer NSString&*)CFPreferencesCopyAppValue(CFSTR(&someKey&), CFSTR(&pany.someapp&));&&& [self&useValue:&value];__bridge_retainedToll-free bridging是双向的。如前所述,ARC不允许一个Objective-C对象的指针转换到的CoreFoundation对象的指针。在ARC, 此代码不会编译成功:&&& CFStringRef&value&=&&(CFStringRef&)[ self someString ];&&& UseCFStringValue&(value);使用__bridge转化才可以编译,但产生的代码是不稳定的:&&& CFStringRef&value&=&&(__bridge& CFStringRef&)[self.someString];&&& UseCFStringValue (value);由于ARC不再管理value的生命周期,它会立即释放value对象的所有权。 在value被传递到UseCFStringValue之前,value可能已经被释放,因此可能会导致崩溃或其他不当行为。通过使用__bridge_retained,我们可以告诉ARC系统将对象所有权转移给程序员。由于所有权发生转移的,程序员现在需要负责释放对象,就像任何其他CF代码:&&& CFStringRef value&=&(__bridge_retained CFStringRef)[selfsomeString];&&& UseCFStringValue(value);&&& CFRelease(value);在Toll-free bridging之外,这些强转的注释也是有用的。任何时候,你需要存储一个Objective-C对象指针到非ARC对象的时候,他们为你铺平道路。 在Cocoa中,经常会看到void *指针,一个突出的例子是sheets。在非ARC中:&&& NSDictionary&*contextDict&=&[NSDictionary dictionary...];&&& [NSApp&beginSheet:&sheetWindow&&&&&&&modalForWindow:&mainWindow&&&&&&&&modalDelegate:&self&&&&&&&didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)&&&&&&&&&&contextInfo:[contextDictretain]];&&&&&&-&(void)sheetDidEnd:&(NSWindow&*)sheet&returnCode:&(NSInteger)code&contextInfo:&(void*)contextInfo&&& {&&&&&&& NSDictionary&*contextDict&=&[(id)contextInfoautorelease];&&&&&&&&if(code&==&NSRunStoppedResponse)&&&&&&&&&&& ...&&& }同样,在ARC中,上述代码会编译失败,因为对象和非对象指针之间的转化是不允许的。然而,使用强转修饰符,我们不光能在ARC中编译通过,而且得到ARC为我们做的必要的内存管理:&&& NSDictionary&*contextDict&=&[NSDictionary dictionary...];&&& [NSApp&beginSheet:&sheetWindow&&&&&&&modalForWindow:&mainWindow&&&&&&&&modalDelegate:&self&&&&&&&didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)&&&&&&&&&&contextInfo:&(__bridge_retained&void*)contextDict];&&&&&&-&(void)sheetDidEnd:&(NSWindow&*)sheet&returnCode:&(NSInteger)code&contextInfo:&(void*)contextInfo&&& {&&&&&&& NSDictionary&*contextDict&=&(__bridge_transfer NSDictionary&*)contextI&&&&&&&&if(code&==&NSRunStoppedResponse)&&&&&&&&&&& ...&&& }总结:__bridge只是简单的传递指针之间的&#20540;,没有所有权的转移。__bridge_transfer用在非Objective-C的指针强转到Objective-C的过程中,不仅转移&#20540;,而且转移对象的所有权。这样,ARC将释放对象的&#20540;。__bridge_retained用在一个Objective-C指针强转到非Objective-C指针的过程中。 不光转移指针&#20540;,而且转移对象的所有权给程序员。程序员需要调用的CFRelease或以其他方式释放对象的所有权。在没有新产生对象的情况下,通常只是使用__bridge做指针&#20540;的传递。一旦在转换过程中产生新的对象,就需要考虑使用__bridge_tranfer 或者__bridge_retained了。将手动内存管理的系统迁移到ARC,大部分遇到的问题就是这种类型转化的问题,不过都很好解决。XCode4.4 给出了非常精准的解决方法建议。在此顺便将我的项目转化过程做一个简要记录,希望对有问题的同学有所帮助:1。将现有程序中的所有编译警告消除,因为迁移到新的LLVM4 编译器,自然有很多警告。2。编译,并运行,确认程序可以正常运行。3。决定程序的那些部分需要转为ARC,那些源程序不需要转。一般第三方,或引用他人的opensource的程序,尽可能保持其原状,不做转化。4。使用xcode4.4提供的ARC工具:Edit-&Refactor-&Convert to ARC project...5。在弹出对话框中,提示要被转化的项目名称和图标,注意在项目名称的左侧有一个小的下拉按钮,用户可以单击,进而显示所有要被转化的源文件列表,在此,用户可以选择那些文件要被转化,那些不需要,只需要取消勾选即可。6. &单击继续按钮,系统会开始检查,并预编译程序看是否可以转为ARC,如果有编译错误,系统将提示你修复这些编译错误.大部分编译错误都是上述的类型转化的问题。7. 解决了这些编译错误,在此尝试启动该ARC工具。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:32215次
排名:千里之外
原创:56篇
转载:23篇
(4)(1)(2)(2)(3)(3)(11)(8)(7)(6)(16)(16)}

我要回帖

更多关于 nsdate nsstring 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信