苹果手机UUID唯一标识替代方案

背景介绍

苹果系统已经在iOS 9.0之后关闭了获取UUID的方法。有时候我们需要定义每个手机的唯一性就很困难。找了很多种方式,都无法满足需求。最后采用idfv + keychian的方式解决这个问题。

可行性

  • 获取一个由苹果分配给应用开发者对每个设备唯一的IDFV作为UUID

顾名思义,是给Vendor标识用户用的,每个设备在所属同一个Vender的应用里,都有相同的值。其中的Vender是指应用提供商,但准确点说,是通过BundleID的反转的前两部分进行匹配,如果相同就是同一个Vender,例如对于com.taobao.app1, com.taobao.app2 这两个BundleID来说,就属于同一个Vender,共享同一个idfv的值。和idfa不同的是,idfv的值是一定能取到的,所以非常适合于作为内部用户行为分析的主id,来标识用户,替代OpenUDID。

  • 注意:如果用户将属于此Vender的所有App卸载,则idfv的值会被重置,即再重装此Vender的App,idfv的值和之前不同。

为了解决这个问题,我引入了keychian保存生成的UUID,如果用户卸载重新安装,那么UUID必定和keychian保存的不一致,则需要 更新keychian的UUID,并且将用户信息以及对应最新的UUID上传服务器,这样可以保证每个用户的UUID的唯一性

一、获取系统的idfv

public static var uuidForVendor: String = {
var deviceUUID = ""
if let idfv = UIDevice.current.identifierForVendor?.uuidString {
deviceUUID = idfv.lowercased()
deviceUUID = deviceUUID.replacingOccurrences(of: "-", with: "")
} else {
//idfv有可能获取不到,那就用
deviceUUID = ZBUUID.uuid
}
return deviceUUID;
}()

二、提供获取idfv获取的方法

获取keychain或userDefaults上的值,没有的话,创建uuid值

func getValueForKey(key: String, userDefaults: Bool, keychain: Bool, accessGroup: String?,synchronizable: Bool) -> String? {

var value: String?
if keychain {
let keychain = KeychainSwift()
keychain.accessGroup = accessGroup
value = keychain.get(key)
}

if value == nil && userDefaults {
value = UserDefaults.standard.value(forKey: key) as? String

//如果为空的话,设置UUID
value = ZBUUID.uuidForVendor

//保存到keychin
self.setValue(value: value!, key: key, userDefaults: userDefaults, keychain: keychain, accessGroup: accessGroup, synchronizable: synchronizable)

}else{
//注意:如果用户将属于此Vender的所有App卸载,则idfv的值会被重置,即再重装此Vender的App,idfv的值和之前不同。
// 所以如果KeyChian存在value的情况下,比较KeyChian中的value与取到 ZBUUID.uuidForVendor,不相等的话,更新KeyChian值

let newValue = ZBUUID.uuidForVendor
if value != newValue {

//如果不为空的话,设置UUID
value = ZBUUID.uuidForVendor

//保存到keychin
self.setValue(value: value!, key: key, userDefaults: userDefaults, keychain: keychain, accessGroup: accessGroup, synchronizable: synchronizable)
}
}
return value
}

三、保存键值到本地沙盒和keychain

func setValue(value: String, key: String, userDefaults: Bool, keychain: Bool, accessGroup: String?, synchronizable: Bool) {

if userDefaults {
UserDefaults.standard.set(value, forKey: key)
UserDefaults.standard.synchronize();
}

if keychain {
let keychain = KeychainSwift()
keychain.accessGroup = accessGroup
keychain.synchronizable = synchronizable
keychain.set(value, forKey: key)
}
}

注意事项

因为使用了Keychian,所以需要开启keychian : targets -- Capabilities -- keychian sharing 打开

结语

通过实验,可以保证每个手机得到的UUID的唯一性,并且卸载重新安装也会更新,保持唯一性,可以作为苹果手机的唯一标识别码。

-如果里面有什么错误,欢迎大家多多指教。
完整的代码请查看:我的github

posted @ 2020-12-22 16:05  凌云幽雨  阅读(796)  评论(0)    收藏  举报