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

Jak mogę uzyskać nowy NSString od aCFString?Jak przekonwertować CFStringRef na NSString?

Odpowiedz

331

NSString i CFStringRef są "Bez opłat mostowych", co oznacza, że ​​można między nimi typować.

Na przykład:

CFStringRef aCFString = (CFStringRef)aNSString; 

działa doskonale i przejrzyście. Podobnie:

NSString *aNSString = (NSString *)aCFString; 

Poprzednia składnia dotyczy MRC. Jeśli używasz ARC, nowa składnia rzutowania wygląda następująco:

NSString *aNSString = (__bridge NSString *)aCFString; 

działa również. Najważniejszą rzeczą, na którą należy zwrócić uwagę, jest to, że CoreFoundation często zwraca obiekty z liczbą referencyjną +1, co oznacza, że ​​muszą zostać zwolnione (wszystkie funkcje CF [Type] Create format to robią).

To dobrze, że w Cocoa można bezpiecznie używać autorelease lub zwolnić, aby je uwolnić.

+85

Jeśli używasz Arc nową składnię decydujący w tym przypadku jest teraz NSString * aNSString = (__bridge NSString *) aCFString – MikeG

+6

Thanks MikeG, musiałem zrobić podobny do odwrotnej konwersji: NSString * str = @ "ABC"; CFStringRef cstrref = (__ bridge CFStringRef) str; – KomodoDave

+2

@NilObject proszę zaktualizować odpowiedź tak, aby zawierała ARC, aby użytkownicy nie musieli sprawdzać komentarzy. Dzięki. –

12

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

NSString *aNSString = (NSString*)aCFString; 

Aby uzyskać więcej informacji, zobacz Toll-Free Bridged Types.

3

Dodam, że nie tylko można przejść z CFString do NSString tylko z rzutowaniem typu, ale działa również w drugą stronę. Możesz upuścić wiadomość CFStringCreateWithCString, która jest jedną z rzeczy, które musisz wydać później. (CF wykorzystuje Create gdzie Cocoa wykorzystuje alloc, tak czy inaczej, byś musiał ją zwolnić.)

Otrzymany kod:

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

Właściwie nie powinno się używać kakao zachować, wydanie autorelease na obiektach Core Foundation w ogólności. Jeśli używasz Garbage Collection (na razie tylko na Mac OS X), te zachowujące, zwalniające, autoreleaseowe połączenia są nieobsługiwane. Stąd wycieki pamięci.

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

Ważne jest, aby docenić asymetrię pomiędzy Fundacją podstawowej i kakao, gdzie zachowują, wydanie i autorelease są no-ops. Jeśli, na przykład, masz wyważone się CFCreate ... Z uwolnienia lub autorelease, będzie przeciekać obiekt w śmieci zebranych środowiska:

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

odwrotnie, używając CFRelease aby zwolnić obiekt wcześniej zatrzymuje się przy użyciu zachować spowoduje w przypadku błędu niedomiaru liczby referencyjnej.


PS: nie mogę wypowiedzieć się na temat odpowiedzi Petera Hoseya - przepraszam, że niepotrzebnie dodałem własne.

2

Wystąpił problem z ARC i liczbą zatrzymań CFStrings. Używanie odpowiedzi NilObjects z drobną korektą działało idealnie dla mnie. Właśnie dodałem zatrzymane np.

CFStringRef cfstringRef = (__bridge_retained CFStringRef)aNsString; 
0

Trzeba go obsada:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName; 
14

Jeśli używasz łuku w nowszych wersjach systemu Mac OS X/Objective C, to prawdziwy proste:

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

Jednak Xcode z przyjemnością ostrzeże Cię, gdy spróbujesz przejąć bezpłatny most CFString do NSString i zaoferujesz automatyczne zawinięcie go w CFBridgingRelease(), , które można zaakceptować i pozwolić na automatyczne wstawienie opakowania po kliknięciu opcji.

+1

Nie jestem pewien, ale myślę, że '(__bridge NSString *)' wystarcza: nie ma sensu zwiększać liczby zatrzymań za pomocą 'CFBridgingRelease()'. –

-3

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

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