Jak przekonwertować CFStringRef na NSString?

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

Jak mogę uzyskać nowy NSStringod aCFString?

papr
źródło

Odpowiedzi:

349

NSString i CFStringRef to „bezpłatne połączenie mostkowe”, co oznacza, że ​​można po prostu między nimi przesyłać między nimi.

Na przykład:

CFStringRef aCFString = (CFStringRef)aNSString;

działa doskonale i przejrzyście. Również:

NSString *aNSString = (NSString *)aCFString;

Poprzednia składnia była dla MRC. Jeśli używasz ARC, nowa składnia rzutowania jest następująca:

NSString *aNSString = (__bridge NSString *)aCFString;

działa również. Kluczową rzeczą do zapamiętania jest to, że CoreFoundation często zwraca obiekty z liczbą odwołań +1, co oznacza, że ​​muszą one zostać zwolnione (robią to wszystkie funkcje formatu CF [Type] Create).

Fajną rzeczą jest to, że w kakao możesz bezpiecznie użyć autowydzielania lub zwolnienia, aby je zwolnić.

NilObject
źródło
88
Jeśli używasz ARC, nowa składnia rzutowania dla tego przypadku to teraz NSString * aNSString = (__bridge NSString *) aCFString
MikeG
6
Dzięki MikeG, musiałem zrobić podobnie w przypadku konwersji odwrotnej: NSString * str = @ "abc"; CFStringRef cstrref = (__ bridge CFStringRef) str;
KomodoDave
2
@NilObject, zaktualizuj swoją odpowiedź, aby uwzględnić ARC, aby osoby wyszukujące nie musiały sprawdzać komentarzy. Dzięki.
Dan Rosenstark
17

Jeśli używasz ARC w najnowszych wersjach Mac OS X / Objective C, jest to naprawdę proste:

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

Jednak Xcode z radością ostrzeże Cię, gdy spróbujesz bezpłatnie połączyć most CFString z NSString i zaoferuje automatyczne zawinięcie go w CFBridgingRelease (), którą możesz zaakceptować i automatycznie wstawić opakowanie, jeśli klikniesz tę opcję.

jasne światło
źródło
3
Nie jestem pewien, ale myślę, że (__bridge NSString *)wystarczy: nie ma sensu zwiększać liczby retencji o CFBridgingRelease().
Cœur
12

Są równoważne, więc możesz po prostu rzucić CFStringRef:

NSString *aNSString = (NSString*)aCFString;

Aby uzyskać więcej informacji, zobacz bezpłatne typy mostów .

Martin Cote
źródło
4

Właściwie nie powinieneś ogólnie używać Cocoa retain, release, autorelease na obiektach Core Foundation. Jeśli używasz funkcji Garbage Collection (na razie tylko w systemie Mac OS X), wywołania te zachowują, zwalniają i automatycznie zwalniają. Stąd wycieki pamięci.

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

Ważne jest, aby docenić asymetrię między Core Foundation i Cocoa - gdzie zatrzymywanie, zwalnianie i automatyczne udostępnianie są zabronione. Jeśli, na przykład, zbalansowałeś CFCreate… z wydaniem lub autorelease, obiekt wycieknie w środowisku zbierania śmieci:

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

I odwrotnie, użycie CFRelease do zwolnienia obiektu, który został wcześniej zachowany przy użyciu funkcji retain, spowoduje błąd niedomiaru liczby odwołań.


PS: nie mogę komentować odpowiedzi Petera Hoseya - przepraszam, że niepotrzebnie dodałem własną.

gavinbeatty
źródło
3

Dodam, że nie tylko możesz przejść z CFString do NSString tylko z rzutowaniem typu, ale działa to również w drugą stronę. Możesz porzucić CFStringCreateWithCStringwiadomość, która jest jedną mniejszą rzeczą, którą musisz opublikować później. (CF używa Createtam, gdzie używa Cocoa alloc, więc tak czy inaczej, musiałbyś go zwolnić.)

Wynikowy kod:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];
Peter Hosey
źródło
2

Miałem problem z ARC i liczbą zachowań CFStrings. Użycie odpowiedzi NilObjects z niewielkimi poprawkami zadziałało dla mnie idealnie. Właśnie dodałem zachowane np.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;
dloomb
źródło
0

Musisz to rzucić:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;
Vincent
źródło
-3

Możesz użyć: With CFStringRef idc;

NSString *sId = [NSString stringWithFormat:@"%@", (NSString*)idc];
vualoaithu
źródło