Я пытаюсь понять , правильный способ получить NSStringот А CFStringRefв АРК? То же самое для движения в противоположном направлении, CFStringRefкак NSStringв ARC?
Как правильно это сделать, не создавая утечек памяти?
Я пытаюсь понять , правильный способ получить NSStringот А CFStringRefв АРК? То же самое для движения в противоположном направлении, CFStringRefкак NSStringв ARC?
Как правильно это сделать, не создавая утечек памяти?
retaining и release-ing, мы должны теперь использовать «красивые» преобразования типа __bridge_transfer, __unsafe_unretainedи __autoreleasing. Ни у кого нет на это времени. (А если серьезно, его труднее читать. На мой взгляд, это совсем не облегчило управление памятью.)
Ответы:
Обычно
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 включится и освободит память для вас.
С другой стороны, вы можете преобразовать a NSString *в a, 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;
NSString->CFString, мы должны использовать __bridge. но когда CFString->NSString, мы должны использовать __bride_transfer. ? И любой побочный эффект, если мы используем, CFReleaseкогда нам тоже не нужно. спасибо :)
CFReleaseдолжна привести к сбою вашей программы, так как вы закончите с несоответствующей операцией сохранения / освобождения, в конечном итоге освободив NULLуказатель.
CFStringRef foo (__bridge CFStringRef)theNSString;andNSString *bar = (__bridge NSString *)theCFString;