Saya mencoba memahami cara yang benar untuk mendapatkan NSString
dari a CFStringRef
di ARC? Sama untuk pergi ke arah sebaliknya, CFStringRef
ke NSString
dalam ARC?
Apa cara yang benar untuk melakukan ini tanpa menyebabkan kebocoran memori?
Saya mencoba memahami cara yang benar untuk mendapatkan NSString
dari a CFStringRef
di ARC? Sama untuk pergi ke arah sebaliknya, CFStringRef
ke NSString
dalam ARC?
Apa cara yang benar untuk melakukan ini tanpa menyebabkan kebocoran memori?
retain
ing dan release
, sekarang kita harus menggunakan pemain "cantik" seperti __bridge_transfer
, __unsafe_unretained
dan __autoreleasing
. Tidak ada yang tidak punya waktu untuk itu. (Dan sungguh, ini lebih sulit untuk dibaca. Menurut saya, itu tidak memfasilitasi manajemen memori sama sekali.)
Jawaban:
Khas
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
dan
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Sekarang, jika Anda ingin tahu mengapa __bridge
kata kunci itu ada, Anda bisa merujuk ke dokumentasi Apple . Di sana Anda akan menemukan:
__bridge
mentransfer penunjuk antara Objective-C dan Core Foundation tanpa pengalihan kepemilikan.
__bridge_retained
atauCFBridgingRetain
melemparkan pointer Objective-C ke pointer Core Foundation dan juga mentransfer kepemilikan kepada Anda. Anda bertanggung jawab untuk memanggil CFRelease atau fungsi terkait untuk melepaskan kepemilikan objek.
__bridge_transfer
atauCFBridgingRelease
memindahkan penunjuk non-Objective-C ke Objective-C dan juga mentransfer kepemilikan ke ARC. ARC bertanggung jawab untuk melepaskan kepemilikan objek.
Artinya, dalam kasus di atas Anda mentransmisikan objek tanpa mengubah kepemilikan. Ini menyiratkan bahwa dalam kedua kasus Anda tidak akan bertanggung jawab untuk menangani memori string.
Mungkin juga ada kasus di mana Anda ingin mentransfer kepemilikan karena alasan tertentu.
Misalnya perhatikan cuplikan berikut
- (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
}
dalam kasus seperti itu, Anda mungkin ingin menyimpan CFRelease
dengan mentransfer kepemilikan saat mentransmisi.
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
NSString * aNSString = (NSString *)CFBridgingRelease(str);
NSLog(@"%@", aNSString);
}
Kepemilikan str
telah ditransfer, jadi sekarang ARC akan masuk dan melepaskan memori untuk Anda.
Sebaliknya, Anda dapat mentransmisikan a NSString *
ke CFString
menggunakan __bridge_retained
cast, sehingga Anda akan memiliki objek tersebut dan harus melepaskannya secara eksplisit dengan menggunakan CFRelease
.
Untuk menyelesaikannya, Anda dapat memiliki
// 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
, kita harus menggunakan __bridge
. tapi kapan CFString->NSString
, kita harus menggunakan __bride_transfer
. ? Dan efek sampingnya, jika kita gunakan CFRelease
saat kita tidak membutuhkannya juga. terima kasih :)
CFRelease
seharusnya membuat program Anda mogok, karena Anda akan berakhir dengan operasi pertahankan / rilis yang tidak sesuai, yang akhirnya melepaskan NULL
penunjuk.
CFStringRef foo (__bridge CFStringRef)theNSString;
danNSString *bar = (__bridge NSString *)theCFString;