Como converter CFStringRef para NSString?

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

Como posso obter um novo NSStringa partir de aCFString?

papr
fonte

Respostas:

349

NSString e CFStringRef são "pontes gratuitas", o que significa que você pode simplesmente alternar entre elas.

Por exemplo:

CFStringRef aCFString = (CFStringRef)aNSString;

funciona de forma perfeita e transparente. Da mesma forma:

NSString *aNSString = (NSString *)aCFString;

A sintaxe anterior era para MRC. Se você estiver usando o ARC, a nova sintaxe de conversão é a seguinte:

NSString *aNSString = (__bridge NSString *)aCFString;

funciona também. O ponto principal a ser observado é que o CoreFoundation geralmente retorna objetos com contagem de referência +1, o que significa que eles precisam ser liberados (todas as funções de formato CF [Tipo] Criar fazem isso).

O bom é que, no Cocoa, você pode usar com segurança o lançamento automático ou a liberação para liberá-los.

NilObject
fonte
88
Se você estiver usando o ARC, a nova sintaxe de conversão para este caso agora é NSString * aNSString = (__bridge NSString *) aCFString
MikeG
6
Obrigado MikeG, tive que fazer semelhante para a conversão reversa: NSString * str = @ "abc"; CFStringRef cstrref = (__ ponte CFStringRef) str;
KomodoDave
2
@NilObject, atualize sua resposta para incluir o ARC, para que os pesquisadores não precisem verificar os comentários. Obrigado.
Dan Rosenstark
17

Se você estiver usando o ARC em versões recentes do Mac OS X / Objective C, é muito fácil:

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

No entanto, o Xcode avisará com prazer quando você tentar ligar gratuitamente a CFString para a NSString e oferecer a quebra automática em CFBridgingRelease (), que você pode aceitar e permitir que ele insira automaticamente o invólucro se você clicar na opção.

luz clara
fonte
3
Não tenho certeza, mas acho que (__bridge NSString *)é suficiente: não faz sentido aumentar a contagem de retenções CFBridgingRelease().
Cœur
12

Eles são equivalentes, então você pode simplesmente converter o CFStringRef:

NSString *aNSString = (NSString*)aCFString;

Para obter mais informações, consulte Tipos de pontes gratuitas .

Martin Cote
fonte
4

Na verdade, você não deve usar Cocoa reter, liberar, liberar automaticamente em objetos do Core Foundation em geral. Se você estiver usando a Garbage Collection (apenas no Mac OS X por enquanto), as chamadas retidas, liberadas e liberadas automaticamente são todas sem opção. Daí vazamentos de memória.

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

É importante apreciar a assimetria entre a Core Foundation e o Cocoa - onde reter, liberar e liberar automaticamente não são ops. Se, por exemplo, você equilibrou um CFCreate… com liberação ou liberação automática, vazará o objeto em um ambiente de coleta de lixo:

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

Por outro lado, usar CFRelease para liberar um objeto que você reteve anteriormente usando reter resultará em um erro de fluxo insuficiente de contagem de referência.


PS: parece que não consigo comentar a resposta de Peter Hosey - desculpe-me por adicionar a minha própria desnecessariamente.

gavinbeatty
fonte
3

Acrescentarei que não apenas você pode ir do CFString para o NSString com apenas uma conversão de tipo, mas também funciona da outra maneira. Você pode soltar a CFStringCreateWithCStringmensagem, que é uma coisa a menos que precisa liberar mais tarde. (O CF usa Createonde o cacau usaalloc , então, de qualquer forma, você precisaria liberá-lo.)

O código resultante:

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

Eu estava tendo um problema com o ARC e a contagem de retenção de CFStrings. Usar a resposta do NilObjects com um pequeno ajuste funcionou perfeitamente para mim. Acabei de adicionar retidos, por exemplo.

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

Você tem que lançá-lo:

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

Você pode usar: Com CFStringRef idc;

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