NSMakeCollectable和ARC不起作用

我正在尝试将我的旧项目转换为ARC。 我有一个创buildUUID的函数,但显然这在使用ARC时不再支持:

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

编译器错误(尝试转换时):'NSMakeCollectable'不可用:在自动引用计数模式下不可用。

所以我的问题是:如何在使用ARC时创buildUUID? 现在还有另外一种方法吗?

NSMakeCollectable()是为了(基本上被弃用的)Objective-C垃圾收集器的好处。 ARC对此一无所知。

您必须使用特殊的cast属性,通常是__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)可能会更清洁。 虽然它们是相同的,所以这取决于你,你发现更可读。

将对象从CFString传输到NSString ,需要让ARC知道如何处理内存pipe理。 在这种情况下,我会build议:

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

这指示CoreFoundation释放对象(如需要平衡Create )。 cocoa将ARC保留对象,当它被分配给uuid

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

为了在整个应用程序中拥有一个单一的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; } 

它是NSMakeCollectable的定义

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

我认为这应该工作

 uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID);