我正在尝试将旧项目转换为ARC。我有一个创建UUID的函数,但显然在使用ARC时不再支持它:
NSString *uuid = nil;
CFUUIDRef theUUID = CFUUIDCreate(kCFAllocatorDefault);
if (theUUID) {
uuid = NSMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, theUUID));
//[uuid autorelease];
CFRelease(theUUID);
}
我收到编译器错误(尝试转换时):'NSMakeCollectable'不可用:在自动引用计数模式下不可用。
所以我的问题是:如何在使用ARC时创建UUID?我现在应该采用另一种方式吗?
答案 0 :(得分: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)
。它们是等价的,所以你觉得它更具可读性。
答案 1 :(得分:8)
将对象从CFString
传输到NSString
时,您需要让ARC了解您希望如何处理内存管理。在这种情况下,我建议:
uuid = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, theUUID));
这指示CoreFoundation释放对象(平衡Create
所需)。当Cocoa分配给uuid
时,Cocoa将保留对象。
答案 2 :(得分:1)
CFUUIDRef theUUID = CFUUIDCreate(NULL);
NSString *s2ndUuid = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, theUUID);
答案 3 :(得分: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;
}
答案 4 :(得分:-2)
它是NSMakeCollectable的定义
NS_INLINE id NSMakeCollectable(CFTypeRef cf) {
return cf ? (id)CFMakeCollectable(cf) : nil;
}
我认为这应该有用
uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID);