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;
Другие вопросы по тегам