通过KeyChain保存并检索值

我试图存储一个整数,并使用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, kSecAttrAccount as String : key, 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 } 

我收到以下错误:

无法将types“__NSCFNumber”的值转换为“NSString”

我尝试玩变数,但没有成功。

我已经更新了Eric的Swift 3版本:

 class KeyChain { class func save(key: String, data: Data) -> OSStatus { let query = [ kSecClass as String : kSecClassGenericPassword as String, kSecAttrAccount as String : key, 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, kSecAttrAccount as String : key, kSecReturnData as String : kCFBooleanTrue, 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) } 

那么,我只是用来源等,使我自己好帮手:享受!

  class func save(key: String, data: NSData) { let query = [ kSecClass as String : kSecClassGenericPassword as String, kSecAttrAccount as String : key, kSecValueData as String : data ] SecItemDelete(query as CFDictionaryRef) let status: OSStatus = SecItemAdd(query as CFDictionaryRef, nil) } class func load(key: String) -> NSData? { let query = [ kSecClass as String : kSecClassGenericPassword, kSecAttrAccount as String : key, kSecReturnData as String : kCFBooleanTrue, kSecMatchLimit as String : kSecMatchLimitOne ] var dataTypeRef :Unmanaged<AnyObject>? let status: OSStatus = SecItemCopyMatching(query, &dataTypeRef) if status == noErr { return (dataTypeRef!.takeRetainedValue() as! NSData) } else { return nil } } class func stringToNSDATA(string : String)->NSData { let _Data = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding) return _Data! } class func NSDATAtoString(data: NSData)->String { var returned_string : String = NSString(data: data, encoding: NSUTF8StringEncoding)! as String return returned_string } class func intToNSDATA(r_Integer : Int)->NSData { var SavedInt: Int = r_Integer let _Data = NSData(bytes: &SavedInt, length: sizeof(Int)) return _Data } class func NSDATAtoInteger(_Data : NSData) -> Int { var RecievedValue : Int = 0 _Data.getBytes(&RecievedValue, length: sizeof(Int)) return RecievedValue } class func CreateUniqueID() -> String { var uuid: CFUUIDRef = CFUUIDCreate(nil) var cfStr:CFString = CFUUIDCreateString(nil, uuid) var nsTypeString = cfStr as NSString var swiftString:String = nsTypeString as String return swiftString } //EXAMPLES // // //Save And Parse Int // var Int_Data = KeyChain.intToNSDATA(555) // KeyChain.save("MAMA", data: Int_Data) // var RecievedDataAfterSave = KeyChain.load("MAMA") // var NSDataTooInt = KeyChain.NSDATAtoInteger(RecievedDataAfterSave!) // println(NSDataTooInt) // // // //Save And Parse String // var string_Data = KeyChain.stringToNSDATA("MANIAK") // KeyChain.save("ZAHAL", data: string_Data) // var RecievedDataStringAfterSave = KeyChain.load("ZAHAL") // var NSDATAtoString = KeyChain.NSDATAtoString(RecievedDataStringAfterSave!) // println(NSDATAtoString) 

Roi Mulia的答案效果很好,这里有一个版本,对Swift 2进行了一些微小的调整:

 class KeyChain { class func save(key: String, data: NSData) -> OSStatus { let query = [ kSecClass as String : kSecClassGenericPassword as String, kSecAttrAccount as String : key, kSecValueData as String : data ] SecItemDelete(query as CFDictionaryRef) return SecItemAdd(query as CFDictionaryRef, nil) } class func load(key: String) -> NSData? { let query = [ kSecClass as String : kSecClassGenericPassword, kSecAttrAccount as String : key, kSecReturnData as String : kCFBooleanTrue, kSecMatchLimit as String : kSecMatchLimitOne ] var dataTypeRef:AnyObject? = nil let status: OSStatus = SecItemCopyMatching(query, &dataTypeRef) if status == noErr { return (dataTypeRef! as! NSData) } else { return nil } } class func stringToNSDATA(string : String)->NSData { let _Data = (string as NSString).dataUsingEncoding(NSUTF8StringEncoding) return _Data! } class func NSDATAtoString(data: NSData)->String { let returned_string : String = NSString(data: data, encoding: NSUTF8StringEncoding)! as String return returned_string } class func intToNSDATA(r_Integer : Int)->NSData { var SavedInt: Int = r_Integer let _Data = NSData(bytes: &SavedInt, length: sizeof(Int)) return _Data } class func NSDATAtoInteger(_Data : NSData) -> Int { var RecievedValue : Int = 0 _Data.getBytes(&RecievedValue, length: sizeof(Int)) return RecievedValue } class func CreateUniqueID() -> String { let uuid: CFUUIDRef = CFUUIDCreate(nil) let cfStr:CFString = CFUUIDCreateString(nil, uuid) let nsTypeString = cfStr as NSString let swiftString:String = nsTypeString as String return swiftString } } 

用法示例:

 let data = KeyChain.intToNSDATA(555) let status = KeyChain.save("MyNumber", data: data) print(status) if let receivedData = KeyChain.load("MyNumber") { let result = KeyChain.NSDATAtoInteger(receivedData) print(result) } 

你正在存储一个数字,而不是一个string,所以你得到一个NSNumber,而不是一个string。 exception是非常清楚的 – 你不能downcast一个NSNumber到一个string – 你可以使用stringValue()来获得一个NSNumber的string表示

 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.stringValue() as! String! } else if string == nil { return nil } } }