2009-03-12 15 views
157
NSString *aNSString; 
CFStringRef aCFString; 
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding); 
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL); 

Come posso ottenere un nuovo NSString da aCFString?Come convertire CFStringRef in NSString?

risposta

331

NSString e CFStringRef sono "Toll free bridged", ovvero è possibile semplicemente digitare tra loro.

Ad 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 utilizzando ARC, la nuova sintassi di casting è la seguente:

NSString *aNSString = (__bridge NSString *)aCFString; 

funziona anche. La cosa fondamentale da notare è che CoreFoundation restituirà spesso oggetti con conteggi di riferimento +1, il che significa che devono essere rilasciati (tutte le funzioni di formattazione CF [Tipo] Crea lo fanno).

La cosa bella è che in Cocoa puoi tranquillamente utilizzare autorelease o release per liberarli.

+85

Se si utilizza ARC, la nuova sintassi casting per questo caso è ora NSString * aNSString = (__bridge NSString *) aCFString – MikeG

+6

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

+2

@NilObject si prega di aggiornare la risposta per includere ARC in modo che gli utenti non debbano controllare i commenti. Grazie. –

12

sono equivalenti, in modo da poter solo lanciare la CFStringRef:

NSString *aNSString = (NSString*)aCFString; 

Per ulteriori informazioni, vedere Toll-Free Bridged Types.

3

Aggiungo che non solo si può passare da CFString a NSString con solo un cast di tipo, ma funziona anche nell'altro modo. È possibile rilasciare il messaggio CFStringCreateWithCString, che è una cosa in meno che è necessario rilasciare in seguito. (CF utilizza Create dove cacao utilizza alloc, quindi in entrambi i casi, si avrebbe avuto bisogno di rilasciarlo.)

Il codice risultante:

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

In realtà, non si dovrebbe usare cacao mantenere, rilascio, autorelease sugli oggetti della Fondazione Core in generalità. Se stai usando Garbage Collection (solo per Mac OS X per ora), quelli che conservano, rilasciano, le chiamate di autorelease sono tutti no-op. Quindi perdite di memoria.

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

E 'importante per apprezzare l'asimmetria tra Nucleo Fondazione e Cocoa, dove conservano, rilascio e autorelease sono-ops. Se, per esempio, si è ottenuta una CFCreate ... con liberazione o autorelease, si fuoriuscire l'oggetto in un ambiente raccolto immondizia:

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

contrario, utilizzando CFRelease per rilasciare un oggetto in precedenza trattenuto usando trattenere risulterà in un errore di underflow del conteggio dei riferimenti.


PS: non riesco a commentare la risposta di Peter Hosey - mi dispiace di aver aggiunto il mio inutilmente.

2

Stavo riscontrando un problema con ARC e il numero di ritenzione di CFStrings. Usare la risposta di NilObjects con un leggero ritocco ha funzionato perfettamente per me. Ho appena aggiunto mantenuto ad es.

CFStringRef cfstringRef = (__bridge_retained CFStringRef)aNsString; 
0

Bisogna cast:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName; 
14

Se stai usando ARC nelle ultime versioni di Mac OS X/Objective C, è vero facile:

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

Tuttavia, Xcode ti avviserà con piacere quando tenti di chiamare il bridge gratuito CFString a NSString e ti offre di riconnetterlo automaticamente in CFBridgingRelease(), che puoi accettare e lasciare che venga automaticamente inserito il wrapper se fai clic sull'opzione.

+1

Non ne sono sicuro, ma penso che '(__bridge NSString *)' sia sufficiente: non è necessario incrementare il conteggio dei ritardi con 'CFBridgingRelease()'. –

-3

Utilizzo: Con CFStringRef idc;

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