Comment convertir CFStringRef en NSString?

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

Comment puis - je obtenir un nouveau NSStringde aCFString?

papr
la source

Réponses:

349

NSString et CFStringRef sont "Toll free bridged", ce qui signifie que vous pouvez simplement les transtyper entre eux.

Par exemple:

CFStringRef aCFString = (CFStringRef)aNSString;

fonctionne parfaitement et de manière transparente. Également:

NSString *aNSString = (NSString *)aCFString;

La syntaxe précédente était pour MRC. Si vous utilisez ARC, la nouvelle syntaxe de diffusion est la suivante:

NSString *aNSString = (__bridge NSString *)aCFString;

fonctionne aussi bien. La chose clé à noter est que CoreFoundation retournera souvent des objets avec un nombre de références +1, ce qui signifie qu'ils doivent être libérés (toutes les fonctions de format CF [Type] Create le font).

La bonne chose est que dans Cocoa, vous pouvez utiliser en toute sécurité autorelease ou release pour les libérer.

NilObject
la source
88
Si vous utilisez ARC, la nouvelle syntaxe de conversion pour ce cas est désormais NSString * aNSString = (__bridge NSString *) aCFString
MikeG
6
Merci MikeG, j'ai dû faire la même chose pour la conversion inverse: NSString * str = @ "abc"; CFStringRef cstrref = (__ pont CFStringRef) str;
KomodoDave
2
@NilObject veuillez mettre à jour votre réponse pour inclure ARC afin que les chercheurs n'aient pas à vérifier les commentaires. Merci.
Dan Rosenstark
17

Si vous utilisez ARC dans les versions récentes de Mac OS X / Objective C, c'est très simple:

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

Cependant, Xcode vous avertira volontiers lorsque vous essayez de relier sans frais CFString à NSString et vous proposera de l'envelopper automatiquement dans CFBridgingRelease (), ce que vous pouvez accepter et laisser insérer automatiquement le wrapper pour vous si vous cliquez sur l'option.

clearlight
la source
3
Je ne suis pas sûr, mais je pense que (__bridge NSString *)c'est suffisant: il ne sert à rien d'incrémenter le compte de conservation avec CFBridgingRelease().
Cœur
12

Ils sont équivalents, vous pouvez donc simplement convertir CFStringRef:

NSString *aNSString = (NSString*)aCFString;

Pour plus d'informations, voir Types pontés sans frais .

Martin Côté
la source
4

En fait, vous ne devriez pas utiliser Cocoa conserver, libérer, autorelease sur les objets Core Foundation en général. Si vous utilisez Garbage Collection (uniquement sur Mac OS X pour le moment), ceux-ci retiennent, libèrent, autorelease les appels sont tous sans opération. D'où des fuites de mémoire.

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

Il est important d'apprécier l'asymétrie entre Core Foundation et Cocoa - où la rétention, la libération et la libération automatique sont interdites. Si, par exemple, vous avez équilibré un CFCreate… avec release ou autorelease, vous fuirez l'objet dans un environnement garbage collection:

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

Inversement, l'utilisation de CFRelease pour libérer un objet que vous avez précédemment conservé à l'aide de conserver entraînera une erreur de dépassement du nombre de références.


PS: je n'arrive pas à commenter la réponse de Peter Hosey - désolé d'avoir ajouté la mienne inutilement.

gavinbeatty
la source
3

J'ajouterai que non seulement vous pouvez passer de CFString à NSString avec uniquement une conversion de type, mais cela fonctionne également dans l'autre sens. Vous pouvez supprimer le CFStringCreateWithCStringmessage, ce qui est une chose de moins que vous devez publier plus tard. (CF utilise Createlà où Cocoa utilise alloc, donc de toute façon, vous auriez dû le publier.)

Le code résultant:

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

J'avais un problème avec l'ARC et le nombre de retenues de CFStrings. L'utilisation de la réponse NilObjects avec une légère modification a parfaitement fonctionné pour moi. Je viens d'ajouter conservé par exemple.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;
dloomb
la source
0

Vous devez le lancer:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;
Vincent
la source
-3

Vous pouvez utiliser: Avec CFStringRef idc;

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