每次調用 CFUUIDCreate 系統都會返回一個全新的唯一 ID. 如果想永久保存這個 ID,需要自己處理,可以一次獲取後,存在 NSUserDefaults,Keychain,Pasteboard 等,下次再從這其中取出。
- (NSString *)createUUID { CFUUIDRef uuid = CFUUIDCreate(NULL); CFStringRef string = CFUUIDCreateString(NULL, uuid); CFRelease(uuid); return (__bridge NSString *)string; }
NSString *uuid = [[NSUUID UUID] UUIDString];
和 CFUUID 一樣, 每次調用 NSUUID 都會獲取到一個新的 UUID,需要自己保存獲取到的 UUID。
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
advertisingIdentifier 由系統保持唯一性,同一個設備上所有應用獲取到 advertisingIdentifier 的都是一樣的。但有兩種方法可以修改這個值,重置系統(設置 -> 通用 -> 還原 -> 抹掉所有內容和設置)或者重置廣告標識符(設置 -> 隱私 -> 廣告 -> 還原廣告標識符),在這兩種情況下都會生成新的advertisingIdentifier
,依然無法保證設備唯一。
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
蘋果的官方文檔:
The value in this property remains the same while the app (or another app from the same vendor) is installed on the iOS device. The value changes when the user deletes all of that vendor’s apps from the device and subsequently reinstalls one or more of them. The value can also change when installing test builds using Xcode or when installing an app on a device using ad-hoc distribution. Therefore, if your app stores the value of this property anywhere, you should gracefully handle situations where the identifier changes.
在同一個設備上不同的 vendor 下的應用獲取到的 IDFV 是不一樣的,而同一個 vendor 下的不同應用獲取的 IDFV 都是一樣的。但如果用戶刪除了這個 vendor 的所有應用,再重新安裝它們,IDFV 就會被重置,和之前的不一樣,也不是設備唯一的。
什麼是 Vendor? 一個 Vendor 是 CFBundleIdentifier——應用標識符的前綴,如下
舉個例子, com.doubleencore.app1 和 com.doubleencore.app2 會獲取到相同的 IDFV,因為它們有相通的 com.doubleencore。但 com.massivelyoverrated 和 net.doubleencore 獲取到的則是不一樣的 IDFV。
以上所有 ID 都不能保證設備唯一,有什麼方式可以獲取設備唯一 ID?
以 IDFV 為例,為保證用戶在刪除應用時,取到的 IDFV 仍和之前的一樣,可以借助 Keychain。使用 SAMKeychain,可以很方便地設置 keychain。 需要注意的是, keychain 在同一個蘋果賬號的不同設備下是同步的,需要設置query.synchronizationMode = SAMKeychainQuerySynchronizationModeNo;
,不在設備間同步這個值,這樣不同設備獲取到的便是不同的 ID,代碼如下:
-(NSString *)getUniqueDeviceIdentifierAsString { NSString *appName=[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; NSString *strApplicationUUID = [SAMKeychain passwordForService:appName account:@"incoding"]; if (strApplicationUUID == nil) { strApplicationUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; NSError *error = nil; SAMKeychainQuery *query = [[SAMKeychainQuery alloc] init]; query.service = appName; query.account = @"incoding"; query.password = strApplicationUUID; query.synchronizationMode = SAMKeychainQuerySynchronizationModeNo; [query save:&error]; } return strApplicationUUID; }
參考資料:
The Developer’s Guide to Unique Identifiers
How to preserve identifierForVendor in ios after uninstalling ios app on device?
What's the difference between UUID, GUID and UDID?