【Swift 開發】IDFA儲存到鑰匙串中保證永久不變,除非系統重灌

weixin_34236869發表於2018-09-16

一、 IDFA值會發生改變的情況

在何種情況下 , 應用的IDFA值會發生改變?

在iOS的設定應用中選擇“重置所有設定”
*沒有影響

在iOS的設定應用中“清除所有的內容和設定”
*advertisingIdentifier 和 identifierForVendor 都會受到影響重新設定變為新值

通過iTunes還原裝置
*advertisingIdentifier 和 identifierForVendor 都會受到影響重新設定變為新值

從裝置上刪除該APP
*如果該APP是某個開發者賬號下在該裝置上的最後一個APP時,會影響identifierForVendor 的值,否則不會影響該欄位的值。

升級應用
*無影響

啟用或關閉“限制廣告追蹤”
*應影響advertisingIdentifier 欄位的具體值

系統升級(通過手機自己升級或通過iTunes升級)
*會改變identifierForVendor 欄位的值

在iOS的設定應用中“重新設定廣告標示符”
*會改變advertisingIdentifier 的值。如果一些應用正在請求該欄位,那麼在該應用重新啟動前該欄位的值並不會發生改變。

通過iTunes進行備份
*對這兩個欄位沒有影響

通過iTunes對備份進行還原
*兩個欄位都會被重置

二、如何保證IDFA不變

將IDFA存到系統的鑰匙串裡面

//  系統鑰匙串管理工具類


import UIKit

class BCSKeyChainTool: NSObject {
    /// 查詢
    static func getKeychainQuery(service: String) -> NSMutableDictionary {
        return NSMutableDictionary.init(objects: [kSecClassGenericPassword, service, service, kSecAttrAccessibleAfterFirstUnlock], forKeys: [kSecClass as! NSCopying, kSecAttrService as! NSCopying, kSecAttrAccount as! NSCopying, kSecAttrAccessible as! NSCopying])
    }
    /// 儲存
    static func save(service: String, data: Any) {
        // Get search dictionary
        let keychainQuery = self.getKeychainQuery(service: service)
        // Delete old item before add new item
        SecItemDelete(keychainQuery)
        // Add new object to search dictionary(Attention:the data format)
        keychainQuery.setObject(NSKeyedArchiver.archivedData(withRootObject: data), forKey: kSecValueData as! NSCopying)
        // Add item to keychain with the search dictionary
        SecItemAdd(keychainQuery, nil)
    }

    /// 載入
    static func load(service: String) -> String {
        var ret: String = ""
        let keychainQuery = self.getKeychainQuery(service: service)
        // Configure the search setting
        // Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
        keychainQuery.setObject(kCFBooleanTrue, forKey: kSecReturnData as! NSCopying)
        keychainQuery.setObject(kSecMatchLimitOne, forKey: kSecMatchLimit as! NSCopying)
        var keyData: CFTypeRef?
        if SecItemCopyMatching(keychainQuery, &keyData) == noErr {
            ret = NSKeyedUnarchiver.unarchiveObject(with: keyData as! Data) as! String
        }
        return ret
    }
    
    /// 刪除
    static func deleteKeyData(service: String) {
        let keychainQuery = self.getKeychainQuery(service: service)
        SecItemDelete(keychainQuery)
    }
    
}


轉載出處

其實和 OC 的SAMKeychain的作用是一樣的

相關文章