Bagaimana cara mengubah CFStringRef ke NSString?

169
NSString *aNSString;
CFStringRef aCFString;
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding);
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL);

Bagaimana saya bisa mendapatkan yang baru NSStringdari aCFString?

papr
sumber

Jawaban:

349

NSString dan CFStringRef adalah "Toll free bridged", artinya Anda cukup mengetikkan di antaranya.

Sebagai contoh:

CFStringRef aCFString = (CFStringRef)aNSString;

bekerja dengan sempurna dan transparan. Juga:

NSString *aNSString = (NSString *)aCFString;

Sintaksis sebelumnya adalah untuk MRC. Jika Anda menggunakan ARC, sintaks casting yang baru adalah sebagai berikut:

NSString *aNSString = (__bridge NSString *)aCFString;

berfungsi juga. Hal utama yang perlu diperhatikan adalah bahwa CoreFoundation akan sering mengembalikan objek dengan jumlah referensi +1, yang berarti mereka harus dilepaskan (semua CF [Type] Buat fungsi format melakukan ini).

Yang menyenangkan adalah di Cocoa Anda dapat menggunakan autorelease atau membebaskan dengan aman.

NilObject
sumber
88
Jika Anda menggunakan ARC, sintaks casting baru untuk kasus ini sekarang adalah NSString * aNSString = (__bridge NSString *) aCFString
MikeG
6
Terima kasih MikeG, saya harus melakukan hal serupa untuk konversi terbalik: NSString * str = @ "abc"; CFStringRef cstrref = (__ menjembatani CFStringRef) str;
KomodoDave
2
@NilObject harap perbarui jawaban Anda untuk menyertakan ARC sehingga pencari tidak perlu memeriksa komentar. Terima kasih.
Dan Rosenstark
17

Jika Anda menggunakan ARC dalam versi terbaru dari Mac OS X / Objective C, itu nyata mudah:

NSString *happyString = (NSString *)CFBridgingRelease(sadString);

Namun, Xcode akan dengan senang hati memperingatkan Anda ketika Anda mencoba untuk membebaskan jembatan CFString ke NSString dan menawarkan untuk secara otomatis membungkusnya dalam CFBridgingRelease (), yang dapat Anda terima dan biarkan secara otomatis memasukkan pembungkus untuk Anda jika Anda mengklik opsi.

cahaya terang
sumber
3
Saya tidak yakin, tapi saya pikir (__bridge NSString *)sudah cukup: tidak ada gunanya menambah retain count CFBridgingRelease().
Cœur
4

Sebenarnya, Anda tidak boleh menggunakan Cocoa retain, release, autorelease pada objek Core Foundation secara umum. Jika Anda menggunakan Garbage Collection (hanya di Mac OS X untuk saat ini), panggilan retensi, lepaskan, autorelease semuanya adalah no-op. Karenanya memori bocor.

Dari Apple http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html :

Penting untuk menghargai asimetri antara Core Foundation dan Cocoa — di mana mempertahankan, melepaskan, dan autorelease adalah hal yang tidak mungkin. Jika, misalnya, Anda telah menyeimbangkan CFCreate ... dengan rilis atau autorelease, Anda akan membocorkan objek di lingkungan sampah yang dikumpulkan:

NSString *myString = (NSString *)CFStringCreate...(...);
// do interesting things with myString...
[myString release]; // leaked in a garbage collected environment

Sebaliknya, menggunakan CFRelease untuk melepaskan objek yang sebelumnya Anda pertahankan menggunakan retain akan menghasilkan kesalahan jumlah referensi aliran bawah.


PS: Sepertinya tidak bisa mengomentari jawaban Peter Hosey - maaf karena menambahkan jawaban saya sendiri yang tidak perlu.

gavinbeatty
sumber
3

Saya akan menambahkan bahwa Anda tidak hanya dapat beralih dari CFString ke NSString hanya dengan tipe-cast, tetapi juga berfungsi sebaliknya. Anda dapat menjatuhkan CFStringCreateWithCStringpesan, yang merupakan satu hal lebih sedikit yang perlu Anda lepaskan nanti. (CF menggunakan Createtempat Cocoa menggunakannya alloc, jadi bagaimanapun, Anda harus melepaskannya.)

Kode yang dihasilkan:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];
Peter Hosey
sumber
2

Saya mengalami masalah dengan ARC dan mempertahankan jumlah CFStrings. Menggunakan jawaban NilObjects dengan sedikit perubahan berhasil untuk saya. Saya baru saja menambahkan misalnya dipertahankan.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;
dloomb
sumber
0

Anda harus melemparkannya:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;
Vincent
sumber
-3

Anda dapat menggunakan: Dengan CFStringRef idc;

NSString *sId = [NSString stringWithFormat:@"%@", (NSString*)idc];
vualoaithu
sumber