如何生成唯一标识符?

24

我需要生成一些整数值,这些值在理论上不会重复。我知道有 arc4random() 函数,但我不确定如何将其与当前日期或其他内容一起使用 :(


3
return counter++ 的问题在哪里?这会在重复之前生成完整的 int 范围。 - Dunes
2
你将会生成这个理论上永远不会重复的 int 值的频率是多少?是在应用程序首次启动时仅一次吗?还是每次启动应用程序都会生成多次? - Joe
我需要为每个已玩游戏生成唯一的ID。游戏结束后,我将使用10个最高分对象(玩家、分数、模式和游戏ID)更新高分数组。有一个Highscore UIViewController从NSUserDefaults中读取这些数据(不作为参数传递)。我需要突出当前用户的游戏表现。因此,为了代码清晰和简洁起见,最好有这样一个ID。 - Centurion
9个回答

54

这将返回一个非常类似于在MySQL中生成的UUID的唯一键。

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

ARC版本:

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

1
这个生成的密钥在计算机的整个生命周期内保证唯一吗?无论应用程序何时退出和打开、重启和关闭?(基本上是到永远的尽头? :)我的意思是,我可以随意使用此函数并将返回值保存在我的应用程序中,而且长时间保持其唯一性吗? - Alex
@DanF 不好意思,我不知道有没有其他方法。我只知道这种方法对我来说似乎是有效的(生成完全唯一的ID)。 - Alex
1
еә”иҜҘдҪҝз”Ё__bridge_transferиҖҢдёҚжҳҜ__bridgeеҗ—пјҹ - derpoliuk
嗨,我想使用这种方法让我的应用程序自动创建唯一的产品ID,但我认为由此方法创建的ID相当长。有没有办法限制uuid中字符的数量?谢谢! - Joris416
1
@Supertecnoboff 我没有说过那个。我说的是,如果你要使用存储机制来跟踪生成的标识符,那么不要使用UUID,因为你可以使用更小的东西(从而节省内存),比如一个简单的整数。考虑你实际需要多少字节,因为它可能不会是16。当你没有集中生成标识符的手段(例如服务器),但仍需要避免冲突时,UUID很有用。它们不会给你100%的确定性,但1/170亿通常已经足够了。 - André Fratelli
显示剩余6条评论

42

3
如果您正在使用CoreData来保存玩过的游戏,NSManagedObjectobjectID应该可以满足您的需求,无需额外的努力。

2
您可以像这样创建 UIApplication、UIDevice 或您喜欢的类别(ARC 示例):
@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()是一个函数,用于生成唯一的标识符。

NSString* UUID () {

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

这将生成一个唯一标识符并存储到NSUserDefault中,以便在应用程序需要时重复使用 - 此标识符将唯一关联到应用程序安装而不是设备,但例如可以用于跟踪订阅APN服务的设备数量等...
之后,您可以按照以下方式使用它:
    NSString *uuid = [[UIApplication sharedApplication] getUUID];

2
一个简单的时间戳(毫秒*10)就可以解决问题:
self.uid = [NSNumber numberWithInteger:[NSDate timeIntervalSinceReferenceDate] * 10000];

这是一个基本解决方案,如果您想要连续创建多个ID,则可能会得到相同的值。 - Hamidreza Vakilian
考虑到Hamid所说的,以简洁明了的方式实现。 - Dima Deplov

2

您可以使用毫秒或更高级的方式GUID来表示时间。


1

你没有说必须是随机的。那么为什么不从某个数字开始,然后只需将上次生成的数字加1。

这种方法应该至少给你提供40亿个独特的数字:

-(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;
}

1
如果您有一个NSDictionary,您可以从最后一项生成一个渐进式ID:
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];

0

如果您使用增量为1的例程,那么一定要小心,特别是如果您的应用程序被删除并重新加载到iDevice上,那么您将不再拥有保存的默认数字。它将从头开始。如果您正在存储用户的分数,您可能还想保存他们的最高分数。最好检查某个日期后的秒数(或毫秒)的时间例程。如上所述的GUID也很好,如果您需要这种唯一性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接