我想了解从ARC NSString
获取CFStringRef
的正确方法?
同样朝着相反的方向,在ARC中CFStringRef
到NSString
在不造成内存泄漏的情况下执行此操作的正确方法是什么?
答案 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
。
要把它包起来,你可以拥有
// 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`
// 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;