Как преобразовать CFStringRef в NSString?

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

Как я могу получить новый NSStringот aCFString?

PAPR
источник

Ответы:

349

NSString и CFStringRef являются «бесплатными мостовыми соединениями», а это означает, что вы можете просто установить тип между ними.

Например:

CFStringRef aCFString = (CFStringRef)aNSString;

работает отлично и прозрачно. Точно так же:

NSString *aNSString = (NSString *)aCFString;

Предыдущий синтаксис был для MRC. Если вы используете ARC, новый синтаксис приведен ниже:

NSString *aNSString = (__bridge NSString *)aCFString;

работает так же. Ключевым моментом, на который следует обратить внимание, является то, что CoreFoundation часто возвращает объекты с числом ссылок +1, что означает, что они должны быть освобождены (все функции формата CF [Type] Create делают это).

Приятно то, что в Какао вы можете безопасно использовать авто-релиз или релиз, чтобы освободить их.

NilObject
источник
88
Если вы используете ARC, новый синтаксис приведения в этом случае теперь NSString * aNSString = (__bridge NSString *) aCFString
MikeG
6
Спасибо MikeG, мне пришлось сделать подобное для обратного преобразования: NSString * str = @ "abc"; CFStringRef cstrref = (__ bridge CFStringRef) str;
KomodoDave
2
@NilObject, пожалуйста, обновите свой ответ, включив в него ARC, чтобы искателям не приходилось проверять комментарии. Спасибо.
Дэн Розенстарк
17

Если вы используете ARC в последних версиях Mac OS X / Objective C, это реальная легко:

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

Тем не менее, Xcode с радостью предупредит вас, когда вы попробуете бесплатно соединить CFString с NSString, и предложит автоматически обернуть его в CFBridgingRelease (), который вы можете принять, и разрешить ему автоматически вставлять оболочку, если вы нажмете эту опцию.

ClearLight
источник
3
Я не уверен, но я думаю, что (__bridge NSString *)достаточно: нет смысла увеличивать счет удержания с CFBridgingRelease().
Cœur
12

Они эквивалентны, так что вы можете просто привести CFStringRef:

NSString *aNSString = (NSString*)aCFString;

Для получения дополнительной информации см. Бесплатные типы мостов .

Мартин Кот
источник
4

На самом деле, вы не должны использовать Cocoa retain, release, autorelease для объектов Core Foundation в целом. Если вы используете сборщик мусора (пока только в Mac OS X), все вызовы retain, release, autorelease - это все no-ops. Отсюда утечки памяти.

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

Важно оценить асимметрию между основной основой и какао, где удержание, высвобождение и авто-релиз не допускаются. Если, например, вы сбалансировали CFCreate ... с выпуском или автоматическим выпуском, вы утечете объект в среде сбора мусора:

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

И наоборот, использование CFRelease для освобождения объекта, который вы ранее сохранили, используя retain, приведет к ошибке опустошения счетчика ссылок.


PS: не могу комментировать ответ Питера Хоси - извините за добавление моего собственного излишне.

gavinbeatty
источник
3

Я добавлю, что вы можете не только перейти от CFString к NSString только с приведением типа, но и работать по-другому. Вы можете отбросить CFStringCreateWithCStringсообщение, которое вам нужно выпустить позже. (CF использует, Createгде использует какаоalloc , так что в любом случае вам бы пришлось его выпустить.)

Полученный код:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];
Питер Хоси
источник
2

У меня была проблема с ARC и счетом сохранения CFStrings. Использование ответа NilObjects с небольшим изменением отлично сработало для меня. Я только добавил сохранил например.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;
dloomb
источник
0

Вы должны разыграть это:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;
Винсент
источник
-3

Вы можете использовать: с CFStringRef idc;

NSString *sId = [NSString stringWithFormat:@"%@", (NSString*)idc];
vualoaithu
источник