2015-06-08 24 views
6

aracılığıyla değeri kaydedin ve alın Bir Tamsayı depolamaya çalışıyorum ve KeyChain kullanarak onu geri almaya çalışıyorum.KeyChain

budur bunu kaydetmek nasıl:

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 

} 

aşağıdaki hatayı alıyorum:

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

I Bu onu geri almaya çalıştığınızda nasıl

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) 

    } 

değişkenlerle oynamayı denedi ama başarıya ulaşmadı.

+0

Bu yüzden yanlış kaydetmiyorum veya yanlış mı aldım? Im confused lol @ Paulw11 –

+0

Bu drop-in anahtarlık sarıcı size biraz fikir verebilir… https://github.com/ashleymills/Keychain.swift –

+0

@AshleyMills cevabımı –

cevap

4

Well dize temsilini almak için stringValue() kullanabilirsiniz, sadece kaynak vb dışarı kullanılan ve benim öz güzel bir yardımcı yapılmış : Zevk!

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

Örnek kullanım:

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

Dize değil, bir sayı değil, bir dizeyi değil, bir sayı depolıyorsunuz. istisna oldukça açıktır - Bir String bir NSNumber downcast olamaz - Bir NSNumber

+0

altında görüyorum Neden sonunda "string olarak" eklediniz ve NSNumber değil? –

+0

Çünkü bir dizi istediğini kabul ettim. Zaten bir NSNumber idi. Muhtemelen bir int döndürmek daha mantıklıdır, bu durumda intValue() 'yi kullanırsınız - ancak fonksiyon imzasını değiştirmeniz gerekecektir. Teoride, 'gibi! String! 'Dize olarak StringValue() her zaman bir dize döndürür – Paulw11

+0

Önümde kodun bulunmaması, derleyicinin' stringValue 'ile ilgili bilmediği konusunda şikâyette bulunmak için 'string'' 'NSNumber'' 'i down down' 'stringNalue' ' AnyObject? – Paulw11

2

Roi MULIA en answer eserler burada Swift 2 için birkaç asgari ayarlama ile bir versiyonu Hızlı 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 } 
    } 
} 

Örnek kullanım:

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

Ben ettik güncelleme Eric'in versiyonu için çok iyi

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

Bir dize değeri saklamak/almak için bunu kullanarak bir hata alın. Dizgiyi kaydetmede hata yok, ancak alma, alınan Data (en az, bir .count of 24) değil, alınanData.to (type: String.self) **, ** gibi geri dönüyor sıfırdır. Düşüncesi olan var mı? – ConfusionTowers

+0

@ConfusionTowers Hatayı yeniden oluşturamıyorum. Kodunu gönderebilir misin? –

+0

Bu kod ile bu satırda 'return self.withUnsafeBytes {$ 0.pointee} 'hatam var. Kilitlenme raporunda "KERN_INVALID_ADDRESS" yazıyor. Ancak bu hata sadece iOS 10.3.3 ile iPhone 5'ler halinde gerçekleşir. Iphone 6s + 10.2 ve iPad + 11.2 hepsi tamam! Bazı fikirler? – strano