NSString в CFStringRef и CFStringRef в NSString в ARC?
Я пытаюсь понять правильный способ получения NSString
из CFStringRef
в дуге? То же самое для движения в противоположном направлении, CFStringRef
в NSString
в дуге?
Как правильно сделать это, не создавая утечек памяти?
1 ответ
Типично
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
а также
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Теперь, если вы хотите знать, почему __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
}
в таком случае вы можете сохранить 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;