NSMakeCollectable y ARC no funciona

Estoy intentando convertir mi antiguo proyecto a ARC. Tengo una function que crea UUID, pero aparentemente esto ya no es compatible cuando se usa ARC:

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

Obtengo el error del comstackdor (al intentar convertir): 'NSMakeCollectable' no está disponible: no está disponible en el modo de conteo automático de references.

Entonces mi pregunta es: ¿cómo creo UUID cuando uso ARC? ¿Hay alguna otra forma que debería usar ahora?

NSMakeCollectable() es para el beneficio del recolector de basura Objective-C (esencialmente desechado). ARC no sabe nada al respecto.

Debe usar un atributo de conversión especial, generalmente __bridge_transfer , para garantizar que la memory no se filtre. __bridge_transfer se usa así:

 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; } 

Editar : como han mencionado otras respuestas, CFBridgingRelease() hace por usted. Entonces, en lugar de utilizar (__bridge_transfer id)uuid , puede ser más limpio escribir CFBridgingRelease(uuid) . Sin embargo, son equivalentes, por lo tanto, depende de usted lo que encuentre más legible.

Cuando transfiere el object de CFString a NSString , debe dejarle saber a ARC cómo desea manejar la administración de memory. En este caso sugeriría:

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

Esto indica a CoreFoundation que libere el object (como se requiere para equilibrar Create ). Cocoa retendrá ARC el object cuando esté asignado a uuid .

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

Para tener un único UUID en toda la aplicación, creo que la mejor manera de lograrlo sería hacer que se ejecute una vez en todo el ciclo de vida de la aplicación.

 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; } 

su definición de NSMakeCollectable

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

Creo que esto debería funcionar

 uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID);