views:

258

answers:

5

I have the following method that should create a 20 character ID (sometimes with a prefix) and return the ID.

It seems to reset on launch and every time I use it it will create the same succession of identical numbers.

+(NSString *)createUniqueIdentifier:(NSString *)withPrefix {
    NSString *outstring = nil;

    if (withPrefix!=nil && ![withPrefix isEqualToString:@""]) {
        outstring = [withPrefix stringByAppendingString:@"-"];
    } else {
        outstring = @"";
    }
    NSInteger ii;
    NSString *allletters = @"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    for (ii=0; ii<20; ii++) {
        outstring = [outstring stringByAppendingString:[allletters substringWithRange:[allletters rangeOfComposedCharacterSequenceAtIndex:random()%[allletters length]]]];
    }

    return outstring;

}

I'm assuming this has something to do with random(), but I don't know what else to use. I think I even got that suggestion from Stack Overflow.

Thanks for any help!

+1  A: 

I think I've figured it out. I changed random() to arc4random() and it magically seems to work now.

Here's the documentation on arc4random that probably has something to do with it:

The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8 bit S-Boxes. The S-Boxes can be in about (2*1700) states. The arc4random() function returns pseudo-random numbers in the range of 0 to (2*32)-1, and therefore has twice the range of rand(3) and random(3) .

The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via arc4random_addrandom().

There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically initializes itself.

mjdth
+2  A: 

My guess is that you probably need to set the seed since it'll use a default one if you don't.

You should at least use something based on the date/time to get something that varies for each run.

Tom Duckering
+5  A: 

When using random() you should set the seed value at program start, ie srandom(time(NULL));

epatel
Is there any downside to using `arc4random()` instead of `random()` with a set seed value?
mjdth
@mjdth Sorry, I have no inside info what actually differs. I'd guess though that `arc4random()` is more advanced as it is designed for crypto strength application, and therefor could take more cpu cycles...
epatel
+1  A: 

If you'd like a completely unique string, I'd use NSProcessInfo to generate one for you by calling:

[[NSProcessInfo processInfo] globallyUniqueString];

Unless you only want it to contain those letters mentioned.

Daniel Tull
A: 

FYI: If you absolutely need unique strings, create a UUID instead of using random, which has a minute chance of getting identical values.

KennyTM