ARC中的NSString到CFStringRef和CFStringRef到NSString?

时间:2013-06-21 03:41:54

标签: objective-c nsstring automatic-ref-counting toll-free-bridging

我想了解从ARC NSString获取CFStringRef的正确方法? 同样朝着相反的方向,在ARC中CFStringRefNSString

在不造成内存泄漏的情况下执行此操作的正确方法是什么?

1 个答案:

答案 0 :(得分:162)

典型地

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

现在,如果您想知道__bridge关键字的原因,可以参考Apple documentation。你会在那里找到:

  

__bridge 在Objective-C和Core Foundation之间传输指针而不转让所有权。

     

__bridge_retained CFBridgingRetain 将指向Core Foundation指针的Objective-C指针强制转换为您,并将所有权转让给您。   您有责任调用CFRelease或相关函数来放弃对象的所有权。

     

__bridge_transfer CFBridgingRelease 将非Objective-C指针移至Objective-C,并将所有权转移到ARC。   ARC负责放弃对象的所有权。

这意味着在上述情况下,您在不更改所有权的情况下投射对象。 这意味着在任何情况下你都不会负责处理字符串的内存。

在某些情况下,您可能还希望转让所有权。

例如,请考虑以下代码段

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge NSString *)str;

    NSLog(@"%@", aNSString);

    CFRelease(str); //you have to release the string because you created it with a 'Create' CF function
}

在这种情况下,您可能希望通过在投放时转移所有权来保存CFRelease

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
    NSString * aNSString = (NSString *)CFBridgingRelease(str);

    NSLog(@"%@", aNSString);
}

str的所有权已经转移,所以现在ARC将启动并为您释放内存。

另一方面,您可以使用NSString *强制转换投射CFString__bridge_retained,这样您就拥有了该对象,并且您必须明确释放它使用CFRelease


要把它包起来,你可以拥有

NSString→CFString

// Don't transfer ownership. You won't have to call `CFRelease`
CFStringRef str = (__bridge CFStringRef)string;

// Transfer ownership (i.e. get ARC out of the way). The object is now yours and you must call `CFRelease` when you're done with it
CFStringRef str = (__bridge_retained CFStringRef)string // you will have to call `CFRelease`

CFString→NSString

// Don't transfer ownership. ARC stays out of the way, and you must call `CFRelease` on `str` if appropriate (depending on how the `CFString` was created)
NSString *string = (__bridge NSString *)str;

// Transfer ownership to ARC. ARC kicks in and it's now in charge of releasing the string object. You won't have to explicitly call `CFRelease` on `str`
NSString *string = (__bridge_transfer NSString *)str;