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