How to generate a unique identifier?
Asked Answered
C

9

24

I need to generate some int value that would never repeat (at least theoretically). I know there is arc4random() fnc but I'm not sure how to use it with some current date or smth :(

Channa answered 10/8, 2011 at 19:6 Comment(3)
What would be wrong with return counter++? Will generate the full range of ints before it has to repeat.Guttery
How often will you be generating this int value that would theoretically never repeat? Once the first time app is launched? Once per launch, or multiple times each time the application is ran.Jorrie
I need to generate unique ID for each played game. After game over, I'm updating highscore array with 10 top score objects (player, score, mode and gameID). There is Highscore UIViewController that reads that data (not gets as argument) from NSUserDefaults. I need to highlight current user gameplay. So for the sake of code clearity and simplicity it would be better to have such ID.Channa
B
54

This returns a unique key very similar to UUID generated in MySQL.

+ (NSString *)uuid
{
    CFUUIDRef uuidRef = CFUUIDCreate(NULL);
    CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
    CFRelease(uuidRef);
    return [(NSString *)uuidStringRef autorelease];
}

ARC version:

+ (NSString *)uuid
{
    CFUUIDRef uuidRef = CFUUIDCreate(NULL);
    CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
    CFRelease(uuidRef);
    return (__bridge_transfer NSString *)uuidStringRef;
}
Bogan answered 11/8, 2011 at 12:36 Comment(11)
Is this generated key guaranteed to be unique through the lifetime of the computer? Through quits and openings of the app, restarts and shutdowns? (basically to the end of time? :) What I mean is can I use this function as many times as I want and keep the returned value as long as I want on my app (and still have it unique of course)?Niu
@Niu Has there been any update one way or the other on the guaranteed uniqueness of these generated UUIDs?Marlo
@DanF Nope, not that I know of. The only thing I know is that this method seems to be working for me (generating completely unique IDs, that is)Niu
Should if be __bridge_transfer instead of __bridge?Jiva
Hi, I want to use this method to let my app automatically create unique product ID's, but I think the ID that is created by this method is quite long. Is there a way to limit the amount of characters in the uuid? Thanks!Metrorrhagia
Nothing is guaranteed to be unique without either a database or a sequence, so probabilistic approaches are used instead. UUIDs were created with this in mind. As you can see here random UUIDs have 122 random bits, which is a lot.Jenniejennifer
Quoting the same link: "the annual risk of a given person being hit by a meteorite is estimated to be one chance in 17 billion, which means the probability is about 0.00000000006 (6 × 10−11), equivalent to the odds of creating a few tens of trillions of UUIDs in a year and having one duplicate. In other words, only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%."Jenniejennifer
@AndréFratelli Would it not be possible to just store what ever UDIDs this creates in an NSArray, then if it creates a duplicate, you can just keep calling the method until it creates a new unique ID string?Katherinkatherina
@Katherinkatherina it would, but if you are to use such storage methods then you do not need UUIDs. UUIDs use 16 bytes (128 bits, 122 of which are random) - that's a lot. UUIDs are meant for generating random values with really (really) low probability of collision. If you implement a collision detection mechanisms then they lose their purpose and you are better off with much smaller values.Jenniejennifer
@AndréFratelli But really really low does not equal nothing. Its still possible. I don't see why a simple array or database of some sort can't be used to store the values you already have. Then you know for a fact that there will never be any collisions.Katherinkatherina
@Katherinkatherina I didn't say that. What I said is that if you are going to use a storage mechanism to keep track of generated identifiers, then don't use UUIDs, as you can use something way smaller (thus saving memory), like a simple integer. Consider how many bytes you actually need, as it probably won't be 16. UUIDs are useful when you don't have a centralized means of generating an identifier, such as a server, but still need to avoid collisions. They won't give you 100% certainty, but 1/17 billion is usually good enough.Jenniejennifer
X
42

A simple version to generate UUID (iOS 6 or later).

Objective-C:

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

Swift 3+:

let uuid = UUID().uuidString

It will generate something like 68753A44-4D6F-1226-9C60-0050E4C00067, which is unique every time you call this function, even across multiple devices and locations.

Reference: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUUID_Class/Reference/Reference.html

Xeres answered 15/7, 2014 at 15:53 Comment(0)
G
3

If you are using CoreData to save the played games, NSManagedObject's objectID should serve your purpose without any extra effort.

Gadson answered 11/8, 2011 at 12:10 Comment(0)
V
2

You can use the time in milliseconds or a more advanced way GUID.

Vadnais answered 10/8, 2011 at 19:9 Comment(0)
H
2

You can create a category of UIApplication , UIDevice or as you prefere like this (ARC example)

@interface UIApplication (utilities)
- (NSString*)getUUID;
@end

@implementation UIApplication (utilities)

- (NSString*)getUUID {

    NSUserDefaults *standardUserDefault = [NSUserDefaults standardUserDefaults];

    static NSString *uuid = nil;

    // try to get the NSUserDefault identifier if exist
    if (uuid == nil) {

        uuid = [standardUserDefault objectForKey:@"UniversalUniqueIdentifier"];
    }

    // if there is not NSUserDefault identifier generate one and store it
    if (uuid == nil) {

        uuid = UUID ();
        [standardUserDefault setObject:uuid forKey:@"UniversalUniqueIdentifier"];
        [standardUserDefault synchronize];
    }

    return uuid;
}

@end

UUID () is this function

NSString* UUID () {

    CFUUIDRef uuidRef = CFUUIDCreate(NULL);
    CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
    CFRelease(uuidRef);
    return (__bridge NSString *)uuidStringRef;
}

this generate an unique identifier stored into the NSUserDefault to be reused whenever the application need it - This identifier will unique related to the application installs not to the device, but can be used for example to take trace about the number devices subscribed the APN service etc...

After that you can use it in this way:

    NSString *uuid = [[UIApplication sharedApplication] getUUID];
Heiner answered 5/4, 2013 at 13:26 Comment(0)
S
2

A simple timestamp (milliseconds * 10) should do the trick:

self.uid = [NSNumber numberWithInteger:[NSDate timeIntervalSinceReferenceDate] * 10000];
Seminarian answered 20/11, 2013 at 10:37 Comment(2)
It's a basic solution as if you want to create multiple IDs subsequently you may probably get the same valuesDeviltry
nice and simple way, taking into account what Hamid said.Lydialydian
R
1

You did not say it must be random. So why not start with some number, and then just add by 1 to the last number you generated.

This method should give you at lest 4 billion unique numbers to start with:

-(NSInteger)nextIdentifies;
{
    static NSString* lastID = @"lastID";
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    NSInteger identifier = [defaults integerForKey:lastID] + 1;
    [defaults setInteger:identifier forKey:lastID];
    [defaults synchronize];
    return identifier;
}
Reduction answered 10/8, 2011 at 19:16 Comment(0)
T
1

If you have a NSDictionary, you could generate a progressive id from the last item:

NSInteger maxKey = -1;
for(NSString *key in [YOUR_DICTIONARY allKeys])
{
    NSInteger intKey = [key integerValue];
    if(intKey > maxKey)
    {
        maxKey = intKey;
    }
}
NSString *newKey = [NSString stringWithFormat:@"%d", maxKey + 1];
Tiedeman answered 14/7, 2014 at 18:29 Comment(0)
R
0

You have to be careful, especially if you use the increment by 1 routines, that if your app is deleted and reloaded on the iDevice, that you won't have your saved default number anymore. It will start over from the beginning. If you're storing user's scores, you might want to save their highest number too. Better to check the time routines for seconds (or milliseconds) after a certain date. The GUID mentioned above is good too, if you need that kind of uniqueness.

Runway answered 10/8, 2011 at 21:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.