Подтвердить что ты не робот

NSMakeCollectable и ARC не работают

Я пытаюсь преобразовать свой старый проект в ARC. У меня есть функция, которая создает UUID, но, видимо, это больше не поддерживается при использовании ARC:

NSString *uuid = nil;
    CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault);
    if (theUUID) {
        uuid = NSMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, theUUID));
        //[uuid autorelease];
        CFRelease(theUUID);
    }

Я получаю ошибку компилятора (при попытке конвертировать): "NSMakeCollectable" недоступен: недоступен в режиме автоматического подсчета ссылок.

Итак, мой вопрос: как мне создать UUID при использовании ARC? Есть ли другой способ, который я должен использовать?

4b9b3361

Ответ 1

NSMakeCollectable() предназначен для использования (существенно устаревшего) сборщика мусора Objective-C. ARC ничего не знает об этом.

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

id MakeUUID(void) {
    id result = nil;
    CFUUIDRef uuid = CFUUIDCreate(NULL);
    if (uuid) {
        result = (__bridge_transfer id)uuid; // this "transfers" a retain from CF control to ARC control.
    }
    return result;
}

Изменить. Как уже упоминалось в других ответах, CFBridgingRelease() делает это для вас. Поэтому вместо использования (__bridge_transfer id)uuid может быть более чистым писать CFBridgingRelease(uuid). Они эквивалентны, так что это зависит от вас, что вы найдете более читаемым.

Ответ 2

Когда вы переносите объект с CFString на NSString, вы должны позволить ARC знать, как вы хотите обрабатывать управление памятью. В этом случае я бы предложил:

uuid = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, theUUID));

Это дает команду CoreFoundation освободить объект (как требуется для балансировки Create). Cocoa будет ARC-сохранить объект, когда он назначен uuid.

Ответ 3

CFUUIDRef theUUID = CFUUIDCreate(NULL);

NSString *s2ndUuid = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, theUUID);

Ответ 4

Чтобы иметь единственный UUID для всего приложения, я думаю, что лучший способ достичь этого - запустить его один раз в течение всего жизненного цикла приложения.

static NSString *uuid;
- (NSString *)theCurrentDeviceUniqueIdentifier {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault);
        if (theUUID) {
            uuid = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, theUUID));
            CFRelease(theUUID);
        }
    });

    return uuid;
}

Ответ 5

это определение NSMakeCollectable

NS_INLINE id NSMakeCollectable(CFTypeRef cf) {
   return cf ? (id)CFMakeCollectable(cf) : nil;
}

Я думаю, что это должно работать

uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID);