【问题标题】:How to generate a unique identifier?如何生成唯一标识符?
【发布时间】:2011-08-10 19:06:19
【问题描述】:

我需要生成一些永远不会重复的 int 值(至少在理论上)。我知道有 arc4random() fnc 但我不确定如何将它与当前日期或 smth 一起使用:(

【问题讨论】:

  • return counter++ 有什么问题?将在必须重复之前生成完整的整数范围。
  • 您将多久生成一次理论上永远不会重复的 int 值?一旦第一次启动应用程序?每次启动一次,或每次运行应用程序多次。
  • 我需要为每个玩过的游戏生成唯一的 ID。游戏结束后,我用 10 个最高得分对象(玩家、得分、模式和游戏 ID)更新高分数组。有 Highscore UIViewController 从 NSUserDefaults 读取数据(不是作为参数获取)。我需要强调当前用户的游戏玩法。所以为了代码的清晰和简洁,最好有这样的ID。

标签: iphone objective-c uniqueidentifier


【解决方案1】:

这会返回一个与 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;
}

【讨论】:

  • 这个生成的密钥是否保证在计算机的整个生命周期内都是唯一的?通过退出和打开应用程序,重新启动和关闭? (基本上到时间结束?:) 我的意思是我可以根据需要多次使用此函数,并在我的应用程序上保留返回值只要我想要的时间(当然它仍然是唯一的)?跨度>
  • @Alex 在这些生成的 UUID 的保证唯一性方面是否有任何更新?
  • @DanF 不,我不知道。我唯一知道的是这种方法似乎对我有用(即生成完全唯一的 ID)
  • 应该是__bridge_transfer 而不是__bridge
  • @Supertecnoboff 我没有这么说。我说的是,如果你要使用存储机制来跟踪生成的标识符,那么不要使用 UUID,因为你可以使用更小的东西(从而节省内存),比如简单的整数。考虑一下您实际需要多少字节,因为它可能不会是 16。当您没有集中式生成标识符的方法(例如服务器)但仍需要避免冲突时,UUID 很有用。他们不会给你 100% 的确定性,但 1/170 亿通常就足够了。
【解决方案2】:

生成 UUID 的简单版本(iOS 6 或更高版本)。

目标-C:

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

斯威夫特 3+:

let uuid = UUID().uuidString

它将生成类似于 68753A44-4D6F-1226-9C60-0050E4C00067 的内容,每次调用此函数时都是唯一的,即使跨多个设备和位置也是如此。

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

【讨论】:

    【解决方案3】:

    如果您使用 CoreData 来保存玩过的游戏,NSManagedObjectobjectID 应该可以满足您的目的,而无需任何额外的努力。

    【讨论】:

      【解决方案4】:

      您可以以毫秒为单位或更高级的方式使用时间GUID

      【讨论】:

        【解决方案5】:

        您可以创建一个 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];
        

        【讨论】:

          【解决方案6】:

          一个简单的时间戳(毫秒 * 10)应该可以解决问题:

          self.uid = [NSNumber numberWithInteger:[NSDate timeIntervalSinceReferenceDate] * 10000];
          

          【讨论】:

          • 这是一个基本的解决方案,如果您想随后创建多个 ID,您可能会得到相同的值
          • 好又简单的方法,考虑到哈米德所说的。
          【解决方案7】:

          你没有说它必须是随机的。那么为什么不从某个数字开始,然后将您生成的最后一个数字加 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;
          }
          

          【讨论】:

            【解决方案8】:

            如果你有一个 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];
            

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-12-06
                • 2011-08-06
                • 1970-01-01
                • 1970-01-01
                • 2017-10-20
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多