Come convertire CFStringRef in NSString?


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

Come posso ottenere un nuovo NSStringda aCFString?

Risposte:


349

NSString e CFStringRef sono "Toll free bridged", il che significa che puoi semplicemente digitare tra loro.

Per esempio:

CFStringRef aCFString = (CFStringRef)aNSString;

funziona perfettamente e in modo trasparente. Allo stesso modo:

NSString *aNSString = (NSString *)aCFString;

La sintassi precedente era per MRC. Se stai usando ARC, la nuova sintassi di casting è la seguente:

NSString *aNSString = (__bridge NSString *)aCFString;

funziona pure. La cosa fondamentale da notare è che CoreFoundation restituisce spesso oggetti con conteggi di riferimento +1, il che significa che devono essere rilasciati (tutte le funzioni di formato CF [Type] Create lo fanno).

La cosa bella è che in Cocoa puoi tranquillamente utilizzare il rilascio automatico o il rilascio per liberarli.


88
Se stai usando ARC, la nuova sintassi di casting per questo caso ora è NSString * aNSString = (__bridge NSString *) aCFString
MikeG

6
Grazie MikeG, ho dovuto fare qualcosa di simile per la conversione inversa: NSString * str = @ "abc"; CFStringRef cstrref = (__ bridge CFStringRef) str;
KomodoDave, il

2
@NilObject aggiorna la tua risposta per includere ARC in modo che gli utenti non debbano controllare i commenti. Grazie.
Dan Rosenstark,

17

Se usi ARC nelle ultime versioni di Mac OS X / Obiettivo C, è davvero semplice:

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

Tuttavia, Xcode ti avviserà felicemente quando proverai a caricare gratuitamente il bridge CFString su NSString e ti offrirà di avvolgerlo automaticamente in CFBridgingRelease (), che puoi accettare e lasciarlo inserire automaticamente il wrapper se fai clic sull'opzione.


3
Non ne sono sicuro, ma penso che (__bridge NSString *)sia sufficiente: non ha senso aumentare il conteggio dei trattenuti CFBridgingRelease().
Cœur il


4

In realtà, non dovresti usare Cocoa fidelizzare, rilasciare, rilasciare automaticamente oggetti Core Foundation in generale. Se stai utilizzando Garbage Collection (per ora solo su Mac OS X), le chiamate di conservazione, rilascio e rilascio automatico sono tutte vietate. Da qui la perdita di memoria.

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

È importante apprezzare l'asimmetria tra Core Foundation e Cocoa, in cui la conservazione, il rilascio e il rilascio automatico non sono operativi. Se, ad esempio, hai bilanciato un CFCreate ... con rilascio o rilascio automatico, perderai l'oggetto in un ambiente di raccolta rifiuti:

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

Al contrario, l'utilizzo di CFRelease per rilasciare un oggetto che è stato precedentemente conservato utilizzando la conservazione comporterà un errore di underflow del conteggio dei riferimenti.


PS: non riesco a commentare la risposta di Peter Hosey - scusami per aver aggiunto la mia inutilmente.


3

Aggiungerò che non solo puoi passare da CFString a NSString solo con un cast di tipo, ma funziona anche nell'altro modo. Puoi eliminare il CFStringCreateWithCStringmessaggio, che è una cosa in meno che devi rilasciare in seguito. (CF usa Createdove Cocoa usa alloc, quindi in entrambi i casi, avresti bisogno di rilasciarlo.)

Il codice risultante:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];

2

Stavo riscontrando un problema con ARC e il conteggio dei CFStrings. Utilizzando NilObjects la risposta con una leggera modifica ha funzionato perfettamente per me. Ho appena aggiunto conservato ad es.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;

0

Devi lanciarlo:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;

-3

È possibile utilizzare: con CFStringRef idc;

NSString *sId = [NSString stringWithFormat:@"%@", (NSString*)idc];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.