NSMakeCollectable and ARC doesn't work

后端 未结 5 1050
故里飘歌
故里飘歌 2020-12-16 10:46

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 *uui         


        
相关标签:
5条回答
  • 2020-12-16 11:27
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    
    NSString *s2ndUuid = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, theUUID);
    
    0 讨论(0)
  • 2020-12-16 11:33

    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);
    
    0 讨论(0)
  • 2020-12-16 11:41

    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.

    0 讨论(0)
  • 2020-12-16 11:41

    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.

    0 讨论(0)
  • 2020-12-16 11:43

    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;
    }
    
    0 讨论(0)
提交回复
热议问题