NSString到CFStringRef和CFStringRef到ARC中的NSString吗?


87

我想了解NSStringCFStringRefARC中获取的正确方法吗?同为去相反的方向,CFStringRefNSString在ARC?

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


4
CFStringRef foo (__bridge CFStringRef)theNSString;NSString *bar = (__bridge NSString *)theCFString;

当使用这两个选项时,您能否详细解释到底发生了什么?
zumzum 2013年

不完全的。我不使用ARC,所以我只知道您必须执行此操作,而不是为什么。

1
@GabrielePetronella ARC可以简化编码,缩短代码长度并提高可读性,并减少人为错误的可能性。所以,现在的而不是由照顾的引用计数retain荷兰国际集团和release-ing对象,我们现在必须用“美丽”铸就像__bridge_transfer__unsafe_unretained__autoreleasing。没有人没有时间这样做。(而且,很难理解。在我看来,它根本没有促进内存管理。)

1
@ H2CO3谢谢您的回答。我强烈不同意,特别是最后一句话,但我尊重您的观点:)
Gabriele Petronella

Answers:


177

通常

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

现在,如果您想知道为什么使用__bridge关键字,可以参考Apple文档。在那里您会发现:

__bridge 在Objective-C和Core Foundation之间转移指针,而没有所有权转移。

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

__bridge_transferCFBridgingRelease将非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将a__bridge_retained强制转换为a ,这样您将拥有该对象,并且必须使用显式释放它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;

非常感谢您,这不是很直观,但是感谢您,您从中学到的知识
Sulfkain 2014年

@:小问题。因此,如果我们使用ARC。什么时候NSString->CFString,我们应该使用__bridge。但是什么时候CFString->NSString,我们应该使用__bride_transfer。?还有任何副作用,如果我们CFRelease在不需要的时候使用它。谢谢:)
hqt

@hqt,如果您想要“简单”的方法,是的,您说的是正确的。同样,一个额外的东西CFRelease应该合理地使您的程序崩溃,因为您最终将遇到不匹配的保留/释放操作,最终释放了一个NULL指针。
加布里埃尔·彼得罗内拉2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.