CFUUID
每次調(diào)用 CFUUIDCreate 系統(tǒng)都會(huì)返回一個(gè)全新的唯一 ID. 如果想永久保存這個(gè) ID,需要自己處理,可以一次獲取后,存在 NSUserDefaults,Keychain,Pasteboard 等,下次再從這其中取出。
- (NSString *)createUUID
{
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);
return (__bridge NSString *)string;
}
NSUUID
NSString *uuid = [[NSUUID UUID] UUIDString];
和 CFUUID 一樣, 每次調(diào)用 NSUUID 都會(huì)獲取到一個(gè)新的 UUID,需要自己保存獲取到的 UUID。
Advertiser Identifier
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
advertisingIdentifier 由系統(tǒng)保持唯一性,同一個(gè)設(shè)備上所有應(yīng)用獲取到 advertisingIdentifier 的都是一樣的。但有兩種方法可以修改這個(gè)值,重置系統(tǒng)(設(shè)置 -> 通用 -> 還原 -> 抹掉所有內(nèi)容和設(shè)置)或者重置廣告標(biāo)識(shí)符(設(shè)置 -> 隱私 -> 廣告 -> 還原廣告標(biāo)識(shí)符),在這兩種情況下都會(huì)生成新的advertisingIdentifier,依然無法保證設(shè)備唯一。
Identifier for Vendor (IDFV)
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.
在同一個(gè)設(shè)備上不同的 vendor 下的應(yīng)用獲取到的 IDFV 是不一樣的,而同一個(gè) vendor 下的不同應(yīng)用獲取的 IDFV 都是一樣的。但如果用戶刪除了這個(gè) vendor 的所有應(yīng)用,再重新安裝它們,IDFV 就會(huì)被重置,和之前的不一樣,也不是設(shè)備唯一的。
什么是 Vendor? 一個(gè) Vendor 是 CFBundleIdentifier——應(yīng)用標(biāo)識(shí)符的前綴,如下

舉個(gè)例子, com.doubleencore.app1 和 com.doubleencore.app2 會(huì)獲取到相同的 IDFV,因?yàn)樗鼈冇邢嗤ǖ?com.doubleencore。但 com.massivelyoverrated 和 net.doubleencore 獲取到的則是不一樣的 IDFV。
以上所有 ID 都不能保證設(shè)備唯一,有什么方式可以獲取設(shè)備唯一 ID?
以 IDFV 為例,為保證用戶在刪除應(yīng)用時(shí),取到的 IDFV 仍和之前的一樣,可以借助 Keychain。使用 SAMKeychain,可以很方便地設(shè)置 keychain。 需要注意的是, keychain 在同一個(gè)蘋果賬號(hào)的不同設(shè)備下是同步的,需要設(shè)置query.synchronizationMode = SAMKeychainQuerySynchronizationModeNo;,不在設(shè)備間同步這個(gè)值,這樣不同設(shè)備獲取到的便是不同的 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?