Wie konvertiere ich CFStringRef in NSString?

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

Wie kann ich eine neue bekommen NSStringaus aCFString?

papr
quelle

Antworten:

349

NSString und CFStringRef sind "gebührenfrei überbrückt", was bedeutet, dass Sie einfach zwischen ihnen tippen können.

Beispielsweise:

CFStringRef aCFString = (CFStringRef)aNSString;

funktioniert perfekt und transparent. Gleichfalls:

NSString *aNSString = (NSString *)aCFString;

Die vorherige Syntax war für MRC. Wenn Sie ARC verwenden, lautet die neue Casting-Syntax wie folgt:

NSString *aNSString = (__bridge NSString *)aCFString;

funktioniert auch. Das Wichtigste ist, dass CoreFoundation häufig Objekte mit +1 Referenzzählern zurückgibt, was bedeutet, dass sie freigegeben werden müssen (alle CF [Type] Create-Formatfunktionen tun dies).

Das Schöne ist, dass Sie in Cocoa sicher Autorelease oder Release verwenden können, um sie freizugeben.

NilObject
quelle
88
Wenn Sie ARC verwenden, lautet die neue Casting-Syntax für diesen Fall jetzt NSString * aNSString = (__bridge NSString *) aCFString
MikeG
6
Danke MikeG, ich musste für die umgekehrte Konvertierung ähnlich vorgehen: NSString * str = @ "abc"; CFStringRef cstrref = (__ Brücke CFStringRef) str;
KomodoDave
2
@NilObject Bitte aktualisieren Sie Ihre Antwort, um ARC einzuschließen, damit Suchende die Kommentare nicht überprüfen müssen. Vielen Dank.
Dan Rosenstark
17

Wenn Sie ARC verwenden in neueren Versionen von Mac OS X / Objective C, dann ist es echte einfach:

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

Xcode warnt Sie jedoch gerne, wenn Sie versuchen, CFString gebührenfrei mit NSString zu verbinden, und bietet an, es automatisch in CFBridgingRelease () zu verpacken, das Sie akzeptieren und den Wrapper automatisch für Sie einfügen lassen können, wenn Sie auf die Option klicken.

klares Licht
quelle
3
Ich bin mir nicht sicher, aber ich denke, es (__bridge NSString *)ist genug: Es macht keinen Sinn, die Anzahl der Aufbewahrungen mit zu erhöhen CFBridgingRelease().
Cœur
12

Sie sind äquivalent, sodass Sie einfach das CFStringRef umwandeln können:

NSString *aNSString = (NSString*)aCFString;

Weitere Informationen finden Sie unter Gebührenfreie überbrückte Typen .

Martin Cote
quelle
4

Tatsächlich sollten Sie Cocoa im Allgemeinen nicht für Core Foundation-Objekte verwenden, um sie zu speichern, freizugeben oder automatisch freizugeben. Wenn Sie Garbage Collection verwenden (derzeit nur unter Mac OS X), sind diese Aufbewahrungs-, Freigabe- und Autorelease-Aufrufe allesamt No-Ops. Daher leckt der Speicher.

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

Es ist wichtig, die Asymmetrie zwischen Core Foundation und Cocoa zu verstehen - wo Retention, Release und Autorelease No-Ops sind. Wenn Sie beispielsweise ein CFCreate… mit Release oder Autorelease ausgeglichen haben, verlieren Sie das Objekt in einer Müllsammelumgebung:

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

Umgekehrt führt die Verwendung von CFRelease zum Freigeben eines Objekts, das Sie zuvor mithilfe von Retain beibehalten haben, zu einem Unterlauffehler bei der Referenzzählung.


PS: Ich kann die Antwort von Peter Hosey nicht kommentieren - entschuldige, dass ich meine eigene unnötig hinzugefügt habe.

gavinbeatty
quelle
3

Ich füge hinzu, dass Sie nicht nur mit einer Typumwandlung von CFString zu NSString wechseln können, sondern auch umgekehrt. Sie können die CFStringCreateWithCStringNachricht löschen. Dies ist eine Sache weniger, die Sie später veröffentlichen müssen. (CF verwendet dort, Createwo Kakao verwendet allocwird. In beiden Fällen hätten Sie es freigeben müssen.)

Der resultierende Code:

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

Ich hatte ein Problem mit ARC und der Anzahl der CFStrings. Die Verwendung von NilObjects Antwort mit einer leichten Änderung funktionierte perfekt für mich. Ich habe gerade zB beibehalten hinzugefügt.

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

Du musst es besetzen:

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

Sie können verwenden: Mit CFStringRef idc;

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