In iOS 5 Apple deprecated the [UIDevice uniqueIdentier]
, which returned the UDID (Unique Device Identifier).
This 40 character hex is a unique device ID that is assigned by Apple to each device. This was previously a great way to identify each unique device, or user of your application, and is often used when an app persists data to a remote server. So, what is a developer to do these days?
The most common approach to this problem is to create your own unique identifier and store it in the NSUserDefaults
preferences file.
I previously wrote about NSUserDefaults
and the ability to register default values for user preferences.
The registerDefaults:
method does not actually set the value for the preferences.
It simply says “if you call objectForKey for a specific preference, and is has not yet been explicitly set using setObject:
, then return this default value”.
I was getting caught up thinking that registerDefaults:
actually set and stored the preferences (if they had not yet been set/stored).
This is not the case. The registerDefaults:
method will not overwrite an already stored preference, but it will “overwrite” a previously set default preference.
If you want to store a unique identifier for your user in their preferences, you need to explicitly check for the existence and set it appropriately.
NSString *existingUUID = [defaults objectForKey:@"UUID"];
if (existingUUID == nil){
CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault);
NSString *uuidStr = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidObject);
CFRelease(uuidObject);
[defaults setObject:uuidStr forKey:@"UUID"];
}
NSLog(@"UUID: %@", [defaults objectForKey:@"UUID"]);
Here we are getting the value for the “UUID” preference.
We check if the value returned is nil
. If it is nil, then we have never created it before, so we will create a new UUID and store this in the NSUserDefaults
file.
I was getting stuck on this previously because I was using the registerDefaults:
and was expecting the value to stick after first launching the application.
This was not the case, as a new UUID was being returned each time I would call objectForKey:@"UUID"
.
Again, I was not explicitly setting the value as I have done above, which is the correct approach.
I hope that helps for anyone else that might get tripped up the same way.