简体   繁体   中英

Is this a good way to generate a random string on iPhone?

Here's the code I came up with:

NSString *randomString = @"";
for (int x=0;x<NUMBER_OF_CHARS;x++) {
  randomString = [randomString stringByAppendingFormat:@"%c", (char)(65 + (arc4random() % 25))];
}
return randomString;

EDIT:

To answer the comments:

1) I'm mostly concerned with brevity of code.

2) I also wonder if this is secure against guessing the string, and/or proof against collisions, if NUMBER_OF_CHARS is a high number (say 40) - not for this application, but in other cases.

3) Also, is there is a faster way if I want to make a ton of strings some day? This seems like it will be slow, since it makes an object each time through the loop.

If NUMBER_OF_CHARS is compile-time constant, you can speed up your code by avoiding repeated object creation. You can make your program shorter by one line, too:

char data[NUMBER_OF_CHARS];
for (int x=0;x<NUMBER_OF_CHARS;data[x++] = (char)('A' + (arc4random_uniform(26))));
return [[NSString alloc] initWithBytes:data length:NUMBER_OF_CHARS encoding:NSUTF8StringEncoding];

As far as I know, arc4random_uniform should be good enough for cryptographic applications, but you may need to consult a cryptography expert if the data that you are planning to protect is of high value to you or especially to your clients.

EDIT : Edited in response to nielsbot 's comment.

FWIW, I'd favor Vincent Gable's suggestion of using a UUID. If you are set on the suggested algorithms, you can get a little bit more variance by using something like this variant of nielsbot's code (just replace the string of characters with whatever you want to include as part of your random strings)...

const NSUInteger NUMBER_OF_CHARS = 40 ;
NSString * CreateRandomString()
{
    static char const possibleChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    unichar characters[NUMBER_OF_CHARS];
    for( int index=0; index < NUMBER_OF_CHARS; ++index )
    {
        characters[ index ] = possibleChars[arc4random_uniform(sizeof(possibleChars)-1)];
    }

    return [ NSString stringWithCharacters:characters length:NUMBER_OF_CHARS ] ;
}

You might also consider using a UUID , since they're pretty well studied and widely used . I would probably start there before trying to guarantee the probability of collisions in my hand-rolled solution.

Here's a fast way to do this, if you will be doing this a lot

const NSUInteger NUMBER_OF_CHARS = 40 ;

NSString * CreateRandomString()
{
    unichar characters[NUMBER_OF_CHARS];
    for( int index=0; index < NUMBER_OF_CHARS; ++index )
    {
        characters[ index ] = 'A' + arc4random_uniform(26) ;
    }

    return [ NSString stringWithCharacters:characters length:NUMBER_OF_CHARS ] ;
}

Another variant to the existing answers. I am posting this because it (seems) to be better performance wise, as it makes a single call to the ARC4 API.

NSString *random32CharacterString() {
    static const int N = 32; // must be even

    uint8_t buf[N/2];
    char sbuf[N];
    arc4random_buf(buf, N/2);
    for (int i = 0; i < N/2; i += 1) {
        sprintf (sbuf + (i*2), "%02X", buf[i]);
    }    
    return [[NSString alloc] initWithBytes:sbuf length:N encoding:NSASCIIStringEncoding];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM