苹果手机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  凌云幽雨  阅读(615)  评论(0编辑  收藏  举报