我们许多现有的应用程序都高度依赖此属性来唯一标识特定设备。那么我们该如何解决这个问题呢?
特别注意事项
不要使用uniqueIdentifier属性。要创建与您的应用程序特定的唯一标识符,您可以调用CFUUIDCreate函数创建UUID,并使用NSUserDefaults类将其写入默认数据库。
但是如果用户卸载并重新安装该应用程序,该值将不同。
我们许多现有的应用程序都高度依赖此属性来唯一标识特定设备。那么我们该如何解决这个问题呢?
特别注意事项
不要使用uniqueIdentifier属性。要创建与您的应用程序特定的唯一标识符,您可以调用CFUUIDCreate函数创建UUID,并使用NSUserDefaults类将其写入默认数据库。
但是如果用户卸载并重新安装该应用程序,该值将不同。
CFUUIDCreate
创建的UUID,如果用户卸载并重新安装应用程序,则是唯一的:每次都会获得一个新的UUID。
但您可能希望它不是唯一的,即当用户卸载并重新安装应用程序时,它应该保持不变。这需要一些努力,因为最可靠的每个设备标识符似乎是MAC地址。您可以查询MAC并将其用作UUID。
编辑:当然,需要始终查询同一接口的MAC。我想最好的选择是使用en0
。即使接口没有IP / 被关闭,MAC也始终存在。
编辑2:正如其他人指出的那样,自iOS 6以来首选解决方案是-[UIDevice identifierForVendor]。在大多数情况下,您应该能够将其用作旧的-[UIDevice uniqueIdentifier]
的替代品(但是,Apple似乎希望您在应用程序第一次启动时创建UUID)。
编辑3:因此,不要将MAC用作UUID,使用使用MAC创建哈希值。每次都将生成相同的结果,即使跨重新安装和应用程序(如果以相同方式进行散列)。无论如何,现在(2013年)除非您需要在iOS< 6.0上获得“稳定”的设备标识符,否则不再需要。
编辑 4: 在 iOS 7 中,为了防止使用 MAC 作为 ID 的基础 方案,Apple 现在始终返回一个固定值。因此,你现在应该使用-[UIDevice identifierForVendor] 或创建一个每次安装都不同的 UUID。
现在你可以使用替代Apple UDID
的方式了。友好的gekitz编写了一个基于设备mac地址和包标识符生成某种类型的UDID
的UIDevice
类别。
您可以在github上找到代码。
02:00:00:00:00:00
。
点击这里查看:https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW34 - Hejazi根据@moonlight提出的链接,我进行了几项测试,看起来这是最好的解决方法。正如@DarkDust所说,该方法会检查始终可用的en0
。
有两个选项:
uniqueDeviceIdentifier
(MAC地址+CFBundleIdentifier的MD5)
和uniqueGlobalDeviceIdentifier
(MAC地址的MD5),它们总是返回相同的值。
以下是我进行的测试(使用真实设备):
#import "UIDevice+IdentifierAddition.h"
NSLog(@"%@",[[UIDevice currentDevice] uniqueDeviceIdentifier]);
NSLog(@"%@",[[UIDevice currentDevice] uniqueGlobalDeviceIdentifier]);
XXXX21f1f19edff198e2a2356bf4XXXX - (WIFI)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (WIFI)全局应用程序UDIDXXXX21f1f19edff198e2a2356bf4XXXX - (3G)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (3G)全局应用程序UDIDXXXX21f1f19edff198e2a2356bf4XXXX - (GPRS)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (GPRS)全局应用程序UDIDXXXX21f1f19edff198e2a2356bf4XXXX - (AirPlane mode)UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (AirPlane mode)全局应用程序UDIDXXXX21f1f19edff198e2a2356bf4XXXX - (Wi-Fi)删除并重新安装应用程序后的UDID
XXXX7dc3c577446a2bcbd77935bdXXXX - (Wi-Fi)删除并安装应用程序后的全局应用程序UDID
希望这对您有用。
编辑:
正如其他人指出的那样,在iOS 7中,该解决方案已不再有用,因为uniqueIdentifier
已不再可用,并且查询MAC地址现在始终返回02:00:00:00:00:00。
请看这个:
我们可以使用Keychain而不是NSUserDefaults
类来存储由CFUUIDCreate
创建的UUID
。
通过这种方式,我们可以避免在重新安装时重新创建UUID
,即使用户卸载并重新安装,也可以获得相同的UUID
。
UUID
仅在用户重置设备时才会重新创建。
我已经尝试了SFHFKeychainUtils这种方法,它非常好用。
- (NSString *)createNewUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [(NSString *)string autorelease];
}
在你的应用程序首次启动时,你可以将它存储在键链(Keychain)
中。因此,在第一次启动后,我们可以直接从键链中使用它,而无需重新生成。使用键链来存储的主要原因是: 当你将UUID
设置为键链时,即使用户完全卸载然后重新安装应用程序,它也会持久存在。 因此,这是一种永久存储的方式,这意味着该密钥将始终唯一。
#import "SSKeychain.h"
#import <Security/Security.h>
在应用程序启动时包含以下代码:
// getting the unique key (if present ) from keychain , assuming "your app identifier" as a key
NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];
if (retrieveuuid == nil) { // if this is the first time app lunching , create key for device
NSString *uuid = [self createNewUUID];
// save newly created key to Keychain
[SSKeychain setPassword:uuid forService:@"your app identifier" account:@"user"];
// this is the one time process
}
从sskeychain下载SSKeychain.m和.h文件,将它们拖到你的项目中,并在项目中添加“Security.framework”。 之后要使用UUID,只需简单地使用:
NSString *retrieveuuid = [SSKeychain passwordForService:@"your app identifier" account:@"user"];
也许您可以使用:
[UIDevice currentDevice].identifierForVendor.UUIDString
苹果的文档描述identifierForVender如下:
该属性的值对于来自同一供应商并在同一设备上运行的应用程序相同。 对于来自不同供应商且在同一设备上的应用程序以及对于不考虑供应商的不同设备上的应用程序,返回不同的值。
您可能想考虑使用OpenUDID
,它可以替代已弃用的UDID
。
基本上,为了匹配UDID
,需要具备以下功能:
OpenUDID
满足上述要求,甚至还具有内置的退出机制以供以后考虑。
请查看http://OpenUDID.org,它指向相应的GitHub。 希望这能有所帮助!
顺便说一句,我会避免使用任何MAC地址替代方案。虽然MAC地址看起来像是一个诱人且通用的解决方案,但请确保这个简单易实现的方法是“有毒的水果”。MAC地址非常敏感,苹果公司很可能在您提交应用之前就废除对其的访问... MAC网络地址用于验证专用LAN(WLAN)或其他虚拟专用网络(VPN)上的某些设备... 它甚至比以前的UDID更敏感!
生成UUID并存储在用户默认设置中? 这样做不好,因为当用户删除应用程序时,它不会持久化。如果他们稍后重新安装在线服务,则不应创建新的设备记录,这将浪费服务器资源并给出包含同一设备两次或更多次的设备列表。如果用户重新安装应用程序,他们将看到多个“Bob's iPhone”。
生成UUID并存储在钥匙串中? 这是我的计划,因为即使卸载应用程序,它也会持久存在。但是,如果备份加密,则在将iTunes备份恢复到新的iOS设备时,钥匙串也会被转移。如果旧设备和新设备都在使用,则可能导致两个包含相同设备ID的设备。即使设备名称相同,它们也应在在线服务中列为两个设备。
生成MAC地址和捆绑ID的哈希值? 这似乎是我需要的最佳解决方案。通过使用捆绑ID进行哈希处理,生成的设备ID不会使设备跨应用程序进行跟踪,并且我可以获得应用程序+设备组合的唯一ID。
可能有帮助:
使用以下代码,它将始终是唯一的,除非您擦除(格式化)设备。
Objective-C:
选项1:这将在每次安装时更改。
UIDevice *uuid = [NSUUID UUID].UUIDString;
选项2:这将对每个供应商/开发者的Apple帐户是独一无二的。
UIDevice *myDevice = [UIDevice currentDevice];
NSString *uuid = [[myDevice identifierForVendor] UUIDString];
Swift 5.X:
选项 1:这将在每次安装时更改。
let uuid = UUID().uuidString
选项2:这将对每个供应商/开发者的苹果帐户是唯一的。
let myDevice = UIDevice.current
let uuid = myDevice.identifierForVendor?.uuidString