如何使用 Objective-c 为 iPhone/iPad 生成设备的唯一 ID

Posted

技术标签:

【中文标题】如何使用 Objective-c 为 iPhone/iPad 生成设备的唯一 ID【英文标题】:How to generate Unique ID of device for iPhone/iPad using Objective-c 【发布时间】:2016-12-07 11:53:19 【问题描述】:

我想知道

这样一旦应用程序安装在设备上,我们就应该跟踪该设备ID

我已经搜索了 iPhone/iPad 的 IMEI,但是在 Objective-c 中是不允许的。

然后我搜索生成 iPhone/iPad 的 UDID,但每次在模拟器上启动它时它都会生成不同的 ID。

【问题讨论】:

***.com/a/39992564/6656894 参考这个答案 UIDevice uniqueIdentifier Deprecated - What To Do Now?的可能重复 【参考方案1】:

是的,UDID 已弃用;出于用户隐私目的,我们不允许获取 UDID。 Apple 不允许获取任何唯一标识设备的标识符,例如 IMEI、MAC 地址、UDID 等。

UUID 是目前最好的方法。但这对于每个供应商来说都是独一无二的。您不能保证每次获得 UUID 字符串时它都是唯一的。最好的办法是将 UUID 字符串存储到手机的 Keychain 中,并在需要时检索它,并附带一个捕获。当您将手机恢复出厂设置时,钥匙串项目将被删除。应牢记这一限制。

更新 - 在 IOS 10.3 测试版中:

Apple 似乎对 iOS 10.3+ 中 Keychain 的工作方式进行了一些更改。当卸载特定供应商的所有应用程序时,存储在钥匙串中的钥匙串项目将被删除。根据苹果公司的说法,即使在应用程序从设备上消失后,应用程序的敏感信息仍然存在可能会导致安全风险,因此他们决定禁止这种行为。

依赖钥匙串存储的开发人员即使在卸载他们的应用程序后也可以利用此WORKAROUND 继续使用预期的功能。根据此解决方法,任何应用程序都可以访问存储在该特定钥匙串访问组中的信息,因此建议为您的数据添加额外的加密层将更加安全地保护它,尽管钥匙串默认加密项目。

更新 - IOS 10.3.3(稳定版): 看来钥匙串项目删除是 ios 10.3.3 早期测试版中的一个 BUG,后来在稳定版本中得到修复。这可能是在测试期间引起的,因为在那个阶段可能会发生奇怪的事情。以后用Keychain应该没问题了。

【讨论】:

这是 10.3 测试版中的一个错误,卸载应用程序正在删除它的钥匙串数据,但现在情况并非如此。 See here @ZaidKhan 是的,我看过那个帖子。是否有任何官方确认或文件表明它再次正常工作?不过,我会更新我的答案。但不能从它或开发者论坛中获得 100% 的保证。 @BadhanGanesh 我认为没有任何官方文档显示 10.3 将删除钥匙串数据,因此不会有您要求的文档。没有? 是的。毕竟这个错误是由开发人员发现的。我想到目前为止,任何发行说明中都没有官方消息说明这个错误。我认为考虑到这个问题不会在未来持续存在是安全的。 iOS 11 现在的状态是什么?另外我想知道钥匙串是否会在使用相同苹果 ID 的所有设备上同步?【参考方案2】:

您可以使用 UUID(通用用户标识)。以下链接包含苹果文档

https://developer.apple.com/reference/uikit/uidevice/1620059-identifierforvendor

https://developer.apple.com/library/content/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW1

您可以将此代码用于 UUID:

//Objective-C

NSString * string =  [[[UIDevice currentDevice] identifierForVendor] UUIDString];

//斯威夫特

let deviceID = UIDevice.currentDevice().identifierForVendor?.UUIDString 

//斯威夫特3

let deviceID = UIDevice.current.identifierForVendor?.uuidString

【讨论】:

设备是否唯一?如果我删除一个应用程序然后重新安装它,它会一样吗? 不,它不会一样。当您删除并重新安装时,它会重新生成一个新的。【参考方案3】:

使用以下代码获取 iOS 设备的 UDID 使用从 URL 下载的 KeychainItemWrapper 类 KeychainItemWrap

NSString *uuid;
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"AC_APP_UUID" accessGroup:nil];
NSString *keychainUUID = [keychain objectForKey:(__bridge id)(kSecAttrAccount)];
NSString *appVersion = [NSString stringWithFormat:@"%@",@"1.0"];
[keychain setObject:appVersion forKey:(__bridge id)(kSecAttrDescription)];
if (keychainUUID==nil||[keychainUUID isKindOfClass:[NSNull class]]||keychainUUID.length==0) 
    uuid = [[NSUUID UUID] UUIDString];
    [keychain setObject:uuid forKey:(__bridge id)(kSecAttrAccount)];
else
    uuid = [keychain objectForKey:(__bridge id)(kSecAttrAccount)];

【讨论】:

【参考方案4】:

2017 年后来到这里的任何人,Apple 已经为此实施了 DeviceCheck。

https://developer.apple.com/documentation/devicecheck#overview

您可以使用 DeviceCheck 查看此特定设备是否已安装或使用您的特定应用。它不会为您提供手机的唯一 ID,但可以让您查看用户是否已完成促销活动。

【讨论】:

【参考方案5】:

您不能获取用户手机的 IMEI 和电话号码,Apple 只能获取这些唯一 ID。

您必须将 UDID 存储在钥匙串中。为此,您必须下载 keychainwrapper 类并存储上述代码生成的 UDID:

   UIDevice *device = [[UIDevice alloc]init]; 
   NSString *idForVend = [NSString stringWithFormat:@"%@", [device identifierForVendor]]; 
   NSLog(@"Identifier For Vendor : %@",idForVend);

点击此链接肯定会解决您的问题:https://***.com/questions/16459879/how-to-store-a-string-in-keychain-ios,iOS? 如果你使用这个如果你删除应用程序并再次安装它将保持相同的 DeviceID。

【讨论】:

【参考方案6】:
#import <AdSupport/AdSupport.h>

NSString* sClientID = [[[ASIdentifierManager sharedManager]advertisingIdentifier] UUIDString];

最佳 UUID 因为:

    它永远不会改变(*即使应用程序将被删除) Apple 批准。

【讨论】:

错了。医生说advertisingIdentifier"may change—for example, if the user erases the device"。我相信它也可以通过转到设置>隐私>广告>重置广告标识符来更改。另外,"In iOS 10.0 and later, the value of advertisingIdentifier is all zeroes when the user has limited ad tracking" 所以它不是唯一的。 @Pang 你有解决办法吗? @Pang 我也需要解决方案【参考方案7】:

解决办法是:

您可以使用 DeviceToken 来做到这一点。 DeviceToken 对于所有移动设备都是唯一的。

代码在这里:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
    
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];

        [[UIApplication sharedApplication] registerForRemoteNotifications];
    
    else
    
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)];
    
    return yes;




- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken


   NSString *AppDeviceToken=[[NSString alloc] initWithFormat:@"%@",deviceToken];
    //NSLog(@"My token is: %@", self.AppDeviceToken);

   AppDeviceToken = [self.AppDeviceToken stringByReplacingOccurrencesOfString:@" " withString:@""];
   AppDeviceToken = [self.AppDeviceToken stringByReplacingOccurrencesOfString:@"<" withString:@""];
   AppDeviceToken = [self.AppDeviceToken stringByReplacingOccurrencesOfString:@">" withString:@""];

    NSLog(@"%@'s Device Token is : %@",[[UIDevice currentDevice] name],AppDeviceToken);

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error

    NSLog(@"Failed to get token, error: %@", error);

设备令牌对所有设备都是唯一的。

【讨论】:

如果您删除应用并在同一设备上重新安装,设备 ID 可能会更改。

以上是关于如何使用 Objective-c 为 iPhone/iPad 生成设备的唯一 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何使 Java 和 Objective-C (iPhone) 之间的 AES 加密相同?

iphone opengl es 2.0,如何使用objective-c类来存储原始数据?

如何将 int 从 iPhone 发送到 Apple Watch 标签(objective-c)

如何使用两个 xib 文件创建一个 Objective-C 类(一个用于 iPhone,另一个用于 iPad)

在 Objective-C (iphone) 中,如何管理“@protocol”引用的内存?

如何在 Objective-C 中的 OS2 中将数据从 Iphone 发送到 Apple Watch