2015-06-08 13 views
6

Ich versuche, eine Ganzzahl zu speichern und mithilfe von KeyChain abzurufen.Wert über KeyChain speichern und abrufen

Dies ist, wie ich es sparen:

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) 

    } 

Dies ist, wie ich versuche, es zu erhalten:

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 

} 

Ich bin die folgende Störung zu erhalten:

Could not cast value of type '__NSCFNumber' to 'NSString'

I versuchte mit den Variablen zu spielen, aber ohne Erfolg.

+0

so ist im es falsch speichern oder falsch abrufen? Im verwirrt lol @ Paulw11 –

+0

Dieser Drop-in-Schlüsselbund Wrapper könnte Ihnen einige Ideen ... https://github.com/ashleymills/Keychain.swift –

+0

@AshleyMills siehe meine Antwort unter –

Antwort

4

Nun zu bekommen, habe ich nur Quelle usw. aus und machte mich selbst schön Helfer : Genießen Sie!

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) 
0

Sie speichern eine Nummer, keine Zeichenfolge, daher erhalten Sie eine NSNummer, keine Zeichenfolge zurück. Die Ausnahme ist ziemlich klar - man kann nicht eine NSNumber in einen String niedergeschlagenen - Sie stringValue() verwenden können, die Zeichenfolgendarstellung eines NSNumber

+0

Also warum am Ende Sie "als String" hinzugefügt und nicht NSNummer? –

+0

Weil ich annahm, dass du eine Saite haben wolltest. Es war schon eine NSNummer. Es ist wahrscheinlich sinnvoller, ein int zurückzugeben. In diesem Fall würden Sie 'intValue()' verwenden - aber Sie müssten Ihre Funktionssignatur ändern. Theoretisch könnte man das 'as! String! 'As stringValue() gibt immer eine Zeichenkette zurück – Paulw11

+0

Ohne den Code vor mir müssen Sie möglicherweise zuerst' string' in 'NSNumber' zurücknehmen, um den Compiler zu stoppen, der sich nicht über' stringValue' informiert 'AnyObject?' – Paulw11

2

Roi Mulia der answer funktioniert sehr gut, hier ist eine Version mit ein paar minimale Anpassungen für 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 
    } 
} 

Beispiel Nutzung:

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) 
} 
12

Ich habe Update Erics Version für 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 } 
    } 
} 

Beispiel Nutzung:

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) 
    } 
+0

Fehler beim Speichern/Abrufen eines Zeichenfolgenwerts. Keine Fehler beim Speichern der Zeichenfolge, aber erhalten, die receivedData ist nicht Null (zumindest hat es eine Zählung von 24), aber die receivedData.to (type: String.self) ** ist ** als zurückkommen Null. Irgendwelche Gedanken? – ConfusionTowers

+0

@ConfusionTowers Ich kann den Fehler nicht reproduzieren. Kannst du deinen Code posten? –

+0

Mit diesem Code habe ich einen Fehler in dieser Zeile 'return self.withUnsafeBytes {$ 0.poittee}'. Der Absturzbericht sagt 'KERN_INVALID_ADDRESS'. Aber dieser Fehler tritt nur bei iPhone 5s mit iOS 10.3.3 auf. Iphone 6s + 10.2 und iPad + 11.2 ist alles in Ordnung! Einige Ideen? – strano

Verwandte Themen