我正在尝试存储一个Integer并使用KeyChain检索它.
这就是我保存它的方式:
func SaveNumberOfImagesTaken() { let key = "IMAGE_TAKEN" var taken = 10 let data = NSKeyedArchiver.archivedDataWithRootObject(taken) let query : [String:AnyObject] = [ kSecClass as String : kSecClassGenericPassword,kSecAttrAccount as String : key,kSecValueData as String : data ] let status : OSStatus = SecItemAdd(query as CFDictionaryRef,nil) }
这是我尝试检索它的方式:
func CheckIfKeyChainValueExitss() -> AnyObject? { var key = "IMAGE_TAKEN" let query : [String:AnyObject] = [ kSecClass as String : kSecClassGenericPassword,kSecReturnData as String : kcfBooleanTrue,kSecMatchLimit as String : kSecMatchLimitOne ] var dataTypeRef :Unmanaged<AnyObject>? let status: OSStatus = SecItemCopyMatching(query,&dataTypeRef) if let op = dataTypeRef?.toOpaque() { let data = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue() if let string: AnyObject? = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? AnyObject? { if key == "IMAGE_TAKEN" { return string as! String! } else if string == nil { return nil } } } return nil }
我收到以下错误:
Could not cast value of type ‘__NSCFNumber’ to ‘NSString’
我试过玩变量但没有成功.
解决方法
我更新了Eric的Swift 3版本:
class KeyChain { class func save(key: String,data: Data) -> OSStatus { let query = [ kSecClass as String : kSecClassGenericPassword as String,kSecValueData as String : data ] as [String : Any] SecItemDelete(query as CFDictionary) return SecItemAdd(query as CFDictionary,nil) } class func load(key: String) -> Data? { let query = [ kSecClass as String : kSecClassGenericPassword,kSecMatchLimit as String : kSecMatchLimitOne ] as [String : Any] var dataTypeRef: AnyObject? = nil let status: OSStatus = SecItemCopyMatching(query as CFDictionary,&dataTypeRef) if status == noErr { return dataTypeRef as! Data? } else { return nil } } class func createUniqueID() -> String { let uuid: CFUUID = CFUUIDCreate(nil) let cfStr: CFString = CFUUIDCreateString(nil,uuid) let swiftString: String = cfStr as String return swiftString } } extension Data { init<T>(from value: T) { var value = value self.init(buffer: UnsafeBufferPointer(start: &value,count: 1)) } func to<T>(type: T.Type) -> T { return self.withUnsafeBytes { $0.pointee } } }
用法示例:
let int: Int = 555 let data = Data(from: int) let status = KeyChain.save(key: "MyNumber",data: data) print("status: ",status) if let receivedData = KeyChain.load(key: "MyNumber") { let result = receivedData.to(type: Int.self) print("result: ",result) }