使用KeychainSwift存储deviceId后为何会发生变更?
问题:DeviceIdentifier莫名变更的原因排查
我用以下代码生成deviceId,但应用运行过程中deviceIdentifier会莫名变更,不符合预期。我怀疑是Keychain读取(标注🔥的行)异常导致重新生成新ID,这有可能吗?问题到底出在哪?
Device类代码
class Device { private let device: UIDevice private let keychain: Keychainable var deviceIdentifier: String { guard let identifier = keychain.decode(forKey: StorageKey.DeviceIdentifier) else { let uuid = device.identifierForVendor!.uuidString keychain.encode(value: uuid, forKey: StorageKey.DeviceIdentifier) return uuid } return identifier } }
Keychain相关代码
import KeychainSwift protocol Keychainable: AnyObject { func encode(value: String, forKey key: String) func decode(forKey key: String) -> String? func delete(forKey key: String) } class Keychain: Keychainable { private let keychain: KeychainSwift init(keychain: KeychainSwift) { self.keychain = keychain } func encode(value: String, forKey key: String) { keychain.set(value, forKey: key) } func decode(forKey key: String) -> String? { keychain.get(key) //🔥 } func delete(forKey key: String) { keychain.delete(key) } }
问题分析与排查方向
你怀疑的Keychain读取异常确实是可能的原因之一,但还有几个更关键的点需要逐一排查:
- KeychainSwift配置不当:KeychainSwift默认的
accessibility属性是.whenUnlocked,如果App在后台锁屏状态下尝试读取Keychain,会直接失败返回nil,触发重新生成ID。另外如果多Target共用Keychain但未配置统一的accessGroup,也会导致跨Target读取失败。 identifierForVendor的特性限制:当用户删除当前开发者的所有App后,identifierForVendor会被系统重置。如果此时Keychain数据也被清除(删除App后对应Keychain条目会被删除),重装App就会生成新ID;但如果是未删除App的情况下ID变更,那大概率是Keychain读取问题。- Keychain读取失败的其他场景:系统Keychain服务临时故障、App的Keychain权限被收回(比如系统隐私设置变更),都会导致
decode返回nil,进而触发新ID生成。 - 强制解包的潜在风险:代码中
device.identifierForVendor!的强制解包虽然正常场景下没问题,但极端情况(如特殊设备/模拟器)下系统返回nil会直接崩溃,建议改为可选绑定处理。
针对你的怀疑,可以做以下验证:
- 在
decode方法中添加日志,记录每次读取的结果,确认是否存在本该有数据却返回nil的情况。 - 调整KeychainSwift的初始化参数,将
accessibility设置为.afterFirstUnlock或.always,确保后台及锁屏状态下能正常读取;多Target场景下配置统一的accessGroup。 - 测试非删除App的场景下重启App/后台唤醒,观察ID是否会变更,定位是否是运行时读取失败导致。
内容的提问来源于stack exchange,提问作者kunass2
相关产品推荐
相关产品推荐

