NSString 到 CFStringRef 和 CFStringRef 到 ARC 中的 NSString?

Posted

技术标签:

【中文标题】NSString 到 CFStringRef 和 CFStringRef 到 ARC 中的 NSString?【英文标题】:NSString to CFStringRef and CFStringRef to NSString in ARC? 【发布时间】:2013-06-18 02:51:23 【问题描述】:

我想了解从 ARC 中的 CFStringRef 获取 NSString 的正确方法? 反方向也一样,ARC 中 CFStringRefNSString

在不造成内存泄漏的情况下,正确的方法是什么?

【问题讨论】:

CFStringRef foo (__bridge CFStringRef)theNSString;NSString *bar = (__bridge NSString *)theCFString; 您能否详细解释一下使用这两个选项时实际发生的情况? 不完全。我不使用 ARC,所以我只知道你必须这样做,但不是为什么。 @GabrielePetronella ARC 应该让编码变得简单、代码更短、更易读,并减少人为错误的可能性。所以,现在我们不必处理retaining 和release-ing 对象的引用计数,我们现在必须使用像__bridge_transfer__unsafe_unretained__autoreleasing 这样的“漂亮”类型转换。没有人没有时间这样做。 (说真的,它更难阅读。在我看来,它根本不利于内存管理。) @H2CO3 谢谢你的回答。我非常不同意,尤其是最后一句话,但我尊重你的观点:) 【参考方案1】:

通常

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

现在,如果您想知道为什么会有__bridge 关键字,可以参考Apple documentation。在那里你会发现:

__bridge 在 Objective-C 和 Core Foundation 之间转移一个指针,但不转移所有权。

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

__bridge_transferCFBridgingRelease 将非 Objective-C 指针移动到 Objective-C 并将所有权转移给 ARC。 ARC 负责放弃对象的所有权。

这意味着在上述情况下,您正在转换对象而不更改所有权。 这意味着在这两种情况下,您都将负责处理字符串的内存。

也有可能出于某种原因您想要转让所有权。

例如考虑以下 sn-p

- (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 将启动并为您释放内存。

另一方面,您可以使用__bridge_retained 强制转换将NSString * 转换为CFString,这样您将拥有该对象,并且您必须使用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;

【讨论】:

非常感谢,这不是很直观,但是感谢您,吸取了教训 @:小问题。所以如果我们使用 ARC。当NSString->CFString 时,我们应该使用__bridge。但是当CFString->NSString时,我们应该使用__bride_transfer。 ?还有任何副作用,如果我们在不需要时使用CFRelease。谢谢:) @hqt,如果你想要“简单”的方式,是的,你说的是正确的。此外,额外的CFRelease 应该会合理地使您的程序崩溃,因为您最终会遇到不匹配的保留/释放操作,最终释放NULL 指针。

以上是关于NSString 到 CFStringRef 和 CFStringRef 到 ARC 中的 NSString?的主要内容,如果未能解决你的问题,请参考以下文章

无效的 CfStringRef plist(字典数组)iOS

iphone开发 中文转码问题

NSString 转 UTF-8 的符号匹配问题

ABAddressbook 崩溃 CFStringRef

如何在 DTrace 操作中打印 CFStringRef?

追加到 NSString 方法的开头