2011-12-21 3 views
23

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

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

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

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

ответ

30

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

Вы должны использовать специальный атрибут отливки, обычно __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's control to ARC's control. 
    } 
    return result; 
} 

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

-2

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

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

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

uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID); 
+0

Это приведет к утечке UUID, поскольку у него есть дополнительный 'CFRetain', прикрепленный к вызову' Create'. –

+0

вы можете использовать CFRelease для выпуска – IPaPa

+1

CFRelease что? Вы назначили его на ARC 'id', который больше не может передаваться непосредственно в CFRelease()'. Вы можете вернуть его обратно, но это борьба с ARC. Это то, что 'CFBridgingRelease()' и эквивалентный '__bridge_transfer' построены для адреса. –

8

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

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

Это указывает CoreFoundation освободить объект (как это требуется, чтобы сбалансировать Create). Какао будет удерживать объект ARC, если ему присвоено значение uuid.

1
CFUUIDRef theUUID = CFUUIDCreate(NULL); 

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

Чтобы иметь один 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; 
} 
Смежные вопросы