ARC中的NSString到CFStringRef和CFStringRef到NSString?

zum*_*zum 80 objective-c nsstring automatic-ref-counting toll-free-bridging

我试图了解NSStringCFStringRefARC 获得一个正确的方法?同为去相反的方向,CFStringRefNSString在ARC?

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

Gab*_*lla 165

通常

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
Run Code Online (Sandbox Code Playgroud)

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Run Code Online (Sandbox Code Playgroud)

现在,如果您想知道__bridge关键字的原因,可以参考Apple文档.在那里你会发现:

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

__bridge_retained或者CFBridgingRetain将一个Objective-C指针强制转换为Core Foundation指针,并将所有权转移给您.您有责任调用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
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可能希望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);
}
Run Code Online (Sandbox Code Playgroud)

所有权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`
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)