I'm trying to store an Integer and retrieve it using KeyChain.
This is how I save it:
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) }
This is how I try to retrieve it:
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 }
I'm getting the following error:
Could not cast value of type '__NSCFNumber' to 'NSString'
I tried playing with the variables but without success.
With iCloud Keychain, you can keep your passwords and other secure information updated across your devices. iCloud Keychain remembers things, so that you don't have to. It auto-fills your informationālike your Safari usernames and passwords, credit cards, and Wi-Fi passwords on any device that you approve.
Keychain: The keychain is a secure and encrypted storage place for sensitive data. You can think of it is a database of sensitive information. Keychain Item: This is a registry in the keychain. Item Class: You can think of a class as a template of information you want to store.
What is keychain? iOS system has an interesting thing called key chianš. The keychain is just a data storage for storing all sensitive data, like passwords, certificates etc.
android.security.KeyChain. The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage. Applications accessing the KeyChain normally go through these steps: Receive a callback from an X509KeyManager that a private key is requested.
I've update Eric's version for Swift 5:
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.load(as: T.self) } } }
I've update Eric's version for 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 } } }
Example usage:
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) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With