NSMakeCollectable and ARC doesn't work

家住魔仙堡 提交于 2019-11-27 17:16:34

问题


I'm trying to convert my old project to ARC. I have a function which creates UUIDs, but apparently this is no longer supported when using ARC:

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

I get the compiler error (when trying to convert): 'NSMakeCollectable' is unavailable: not available in automatic reference counting mode.

So my question is: how do I create UUIDs when using ARC? Is there another way which I should now use?


回答1:


NSMakeCollectable() is for the benefit of the (essentially deprecated) Objective-C garbage collector. ARC knows nothing about it.

You must use a special casting attribute, usually __bridge_transfer, to ensure that the memory is not leaked. __bridge_transfer is used like so:

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

Edit: As other answers have mentioned, CFBridgingRelease() does this for you. So instead of using (__bridge_transfer id)uuid, it may be cleaner to write CFBridgingRelease(uuid). They are equivalent though, so it's up to you which you find more readable.




回答2:


When you transfer the object from CFString to NSString, you need to let ARC know how you want to handle memory management. In this case I would suggest:

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

This instructs CoreFoundation to release the object (as is required to balance Create). Cocoa will ARC-retain the object when it is assigned to uuid.




回答3:


CFUUIDRef theUUID = CFUUIDCreate(NULL);

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



回答4:


To have a single UUID across whole app, I think the best way to achieve that would be to have it run once in the whole application lifecycle.

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



回答5:


it's definition of NSMakeCollectable

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

I think this should work

uuid =CFUUIDCreateString(kCFAllocatorDefault, theUUID);


来源:https://stackoverflow.com/questions/8594721/nsmakecollectable-and-arc-doesnt-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!