[[NSUUID UUID] UUIDString] always returning nil

This should be pretty simple:


@import Foundation;

...

NSString *uuid = [[NSUUID UUID] UUIDString];


This ALWAYS returns "nil" object


should return something like: "68753A44-4D6F-1226-9C60-0050E4C00067"


I recently found this about it, and it's definitely nil EVERY SINGLE TIME...


Because of the way NSUUID's are wrappers of CFUUID's in one of the most bizzarre nonsense "toll free bridging" that I have run across in Foundation, NSUUID's cannot be used as keys, stored in another containers for any extended period of time, or even subclassed. You always must use the string representation as the key. In fact the longer you hold on to an NSUUID, the more likely you are to discover that it's underlying representation has been deallocated from under you and it can no longer return the value that it returned shortly after alloc/init. Fun stuff.


SEE: post: Re: Background Session Task state persistence

BugReported:

22939495


- (NSString *)getUUID

{

CFUUIDRef uuid = CFUUIDCreate(NULL);

NSString *uuidStr = (__bridge_transfer NSString *)CFUUIDCreateString(NULL, uuid);

CFRelease(uuid);

return uuidStr;

}


This is also always returning 'nil'

You probably need to provide more context and/or the code surrounding it. I tried it (Xcode 7 and 7.1 beta) on iOS app (simulator & device) and OS X app (Yosemite) and it works fine.

- (void)addGeofenceTimestamp: (CLRegion *)region isEnter:(BOOL)entered

{

NSString *uuidString = [[NSUUID UUID] UUIDString];

NSString *wasEntered = [NSString stringWithFormat:@"%s",(entered?"YES":"NO")];

NSString *regionId = [region identifier];

NSDate *now = [NSDate date];

NSDictionary *dict = [NSDictionary dictionaryWithObjects:@[uuidString, wasEntered, regionId, now]

forKeys:@[@"uuid", @"wasEntered",@"regionId", @"timeStamp"]];


[geofenceCache setObject:dict forKey:uuidString];

NSLog(@"geofenceTimestamp Added to Cache: %@, %@, uuid:%@", now, dict, uuidString);

BOOL result = [self saveGeofenceCache];

[self sendTimestampVerification:uuidString withDictionary:dict];

[LogService logMessage:[NSString stringWithFormat:@"geofenceTimestamp Added to Cache: %s {now: %@, region:%@.", (result?"YES":"NO"), now, dict] withDate:[NSDate date] withCode:LogCodeInfo];

}


when I breakpoint the code and step: the uuidString is always nil

From the looks of your bug report you seem to be reporting that the debugger cannot find the value for the uuid or the string, but the debugger also seems to be reporting that optimizations may have eliminated the variable.


I highly suspect that you are not in fact getting a nil UUID – you are simply seeing artifacts of optimization.


Also your other assertions that it cannot be used as a key in NSDictionary seem incorrect on the face of it – NSUUID conforms to NSCopying and properly implements -isEqual:, which is all that is necessary to be a dictionary key. What issues are you seeing that prevent it from being used as a dictionary key?


As for subclassing you are correct – NSUUID is not meant to be subclassed, but on the face of it I fail to see the utility of doing so. Do you have a use case for doing so in mind? Also as stated in the documentation, NSUUID is not toll-free bridged to CFUUIDRef, as such they cannot be used interchangeably.


I would suspect that the most likely reason you might be having issues is that you might be overreleasing the NSUUID. If you are routinely using __bridge_transfer and __bridge_retained you may be inadvertantly breaking your objects by breaking their ownership graph.


Alternatively you might try verifying you don't have conflicts in some shared library or framework that you are using – in a simple application I can't get [NSUUID UUID] or -UUIDString to return nil.

Okay:


From the looks of your bug report you seem to be reporting that the debugger cannot find the value for the uuid or the string, but the debugger also seems to be reporting that optimizations may have eliminated the variable.


I highly suspect that you are not in fact getting a nil UUID – you are simply seeing artifacts of optimization.


Response..


If I breakpoint the line after: NSString *uuidString = [[NSUUID UUID] UUIDString];

and uuidString is nil, then the optimizer is being WAY TOO AGGRESSIVE. I should be able to access that value at least once.


Next:


Also your other assertions that it cannot be used as a key in NSDictionary seem incorrect on the face of it – NSUUID conforms to NSCopying and properly implements -isEqual:, which is all that is necessary to be a dictionary key. What issues are you seeing that prevent it from being used as a dictionary key?


As for subclassing you are correct – NSUUID is not meant to be subclassed, but on the face of it I fail to see the utility of doing so. Do you have a use case for doing so in mind? Also as stated in the documentation, NSUUID is not toll-free bridged to CFUUIDRef, as such they cannot be used interchangeably.


I would suspect that the most likely reason you might be having issues is that you might be overreleasing the NSUUID. If you are routinely using __bridge_transfer and __bridge_retained you may be inadvertantly breaking your objects by breaking their ownership graph.


Response:


I was actually searching for a reason the string never receives a value, and copy pasted stuff from other threads that may be associated with this issue I am having. SEE Conversation with the title: Re: Background Session Task state persistence. Also, some code I was referring to was from an older topic from before the UUIDString property was added, that I found on Stack Overflow:


-(NSString*) myUUID()

{

    CFUUIDRef newUniqueID = CFUUIDCreate(kCFAllocatorDefault);

    CFStringRef newUniqueIDString = CFUUIDCreateString(kCFAllocatorDefault, newUniqueID);

    NSString *guid = (__bridge NSString *)newUniqueIDString;

    CFRelease(newUniqueIDString);

    CFRelease(newUniqueID);

    return([guid lowercaseString]);

}


This code also came up with nil for some reason.


Lastly:


Alternatively you might try verifying you don't have conflicts in some shared library or framework that you are using – in a simple application I can't get [NSUUID UUID] or -UUIDString to return nil.


There might be something with library coflicts, but I don't believe there is anything defining a class NSUUID, and can't think of any reason there would be a conflict that would affect the call to: [[NSUUID UUID] UUIDString], unless a library we're using is defining such a class,and calling it NSUUID, and that class also had the property UUIDString defined, or there would be and exception.


So, at the very least I have an issue with my system's current configuration and XCode, and have some corruption or some other wacky thing. But, since I am able to reproduce it every single time, I would think someone at Apple might like to SEE it. I would be happy to let someone, at Apple, remote in so you can see for yourself what's happening.


At this point, the only thing I really need is a somewhat reliable Unique String I can use for some messaging between my server and the iOS app, so I can differentiate between asynchronous message responses. So, I will just try coming up with my own function that generates a psuedo UUID string.

"If I breakpoint the line after: NSString *uuidString = [[NSUUID UUID] UUIDString]; and uuidString is nil, then the optimizer is being WAY TOO AGGRESSIVE. I should be able to access that value at least once."


The optimizer is not designed to build code for debuggability, it is designed to build code for performance. If you want debuggability, you should turn off optimizations (which is the default behavior for Debug builds).


"There might be something with library coflicts, but I don't believe there is anything defining a class NSUUID, and can't think of any reason there would be a conflict that would affect the call to: [[NSUUID UUID] UUIDString], unless a library we're using is defining such a class,and calling it NSUUID, and that class also had the property UUIDString defined, or there would be and exception."


It may not be directly an issue with NSUUID in those libraries. I've seen people do really weird things with the runtime that cause all manner of issues far and away from the starting point or intent of the code.


As I mentioned last night, I could not reproduce this issue in a sample application. I just tried the snippets from your bug this morning and I cannot reproduce your issue today either. I suspect whomever eventually recieves your bug may not be able to reproduce the issue with what you have provided either.


This is why we strongly recommend you send a sample application that reproduces the issue when you send in bug reports. You may yourself find that by simplifying the issue down that you no longer can reproduce the problem as well.

Did you use Objective C in your test or Swift? Because in another project I get a valid string in Swift2 but not from Objective C

Objective C, I simply copied and pasted the code you wrote.

Although I never experienced such behavior and the same expression works perfect for me - one thing you write which (I think) is NOT TRUE - you say that NSUUID is "based on CFUUID" and it isn't. Not only NSUUID* is not "toll-free-bridged" to CFUUIDRef (try to cast and bridge then send a message - you'll crash immediately) - the only way to construct one from the other, is either via "exporting" one as a string and initializing the other from that string, or - extracting the "raw uuid 128bit value" and creating the other from it. Not even a special initializer to bridge the worlds.

Just for your info.

[[NSUUID UUID] UUIDString] always returning nil
 
 
Q