2012-06-10 4 views

risposta

46

SecItemCopyMatching è la chiamata giusta per questo. Prima costruiamo nostro dizionario query in modo che gli attributi le voci vengono restituiti nei dizionari, e che tutti gli articoli sono tornati:

NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: 
    (__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnAttributes, 
    (__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit, 
    nil]; 

Come SecItemCopyMatching richiede almeno la classe dei restituiti SecItem s, creiamo un array con tutti le classi ...

NSArray *secItemClasses = [NSArray arrayWithObjects: 
          (__bridge id)kSecClassGenericPassword, 
          (__bridge id)kSecClassInternetPassword, 
          (__bridge id)kSecClassCertificate, 
          (__bridge id)kSecClassKey, 
          (__bridge id)kSecClassIdentity, 
          nil]; 

... e per ogni classe, impostare la classe nella nostra query, chiamata SecItemCopyMatching, e log il risultato.

for (id secItemClass in secItemClasses) { 
    [query setObject:secItemClass forKey:(__bridge id)kSecClass]; 

    CFTypeRef result = NULL; 
    SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); 
    NSLog(@"%@", (__bridge id)result); 
    if (result != NULL) CFRelease(result); 
} 

Nel codice di produzione, si dovrebbe verificare che il OSStatus restituito da SecItemCopyMatching è o errSecItemNotFound (articoli trovati) o errSecSuccess (almeno un elemento è stato trovato).

+0

Grazie! Non l'ho ancora provato, ma sembra la risposta giusta. – noamtm

+2

Lo è. L'ho provato :) –

+0

Ho ottenuto tutti i null nella stampa sia in iPhone che nel simulatore. C'è qualcosa che dovrei fare? – karim

3

Swift 3+ versione che restituisce anche le chiavi (kSecAttrAccount):

open func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { 

     var query: [String: Any] = [ 
      kSecClass : secClass, 
      kSecReturnData : kCFBooleanTrue, 
      kSecReturnAttributes : kCFBooleanTrue, 
      kSecReturnRef : kCFBooleanTrue, 
      kSecMatchLimit : kSecMatchLimitAll 
     ] 

     var result: AnyObject? 

     let lastResultCode = withUnsafeMutablePointer(to: &result) { 
      SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) 
     } 

     var values = [String:String]() 
     if lastResultCode == noErr { 
      let array = result as? Array<Dictionary<String, Any>> 

      for item in array! { 
       if let key = item[kSecAttrAccount] as? String, 
        let value = item[kSecValueData] as? Data { 
        values[key] = String(data: value, encoding:.utf8) 
       } 
      } 
     } 

     return values 
    } 
+0

Usando Swift 3 su Xcode 9.2 questo si blocca su 'let key: String = item [kSecAttrAccount] as! String' con 'Impossibile eseguire il cast del valore di tipo '__NSCFData' (0x109b30348) su 'NSString' (0x1069030d0) .'. Non sono sicuro del perché. –

+1

Cambiare le linee che impostano la chiave e il valore per questo non ha causato l'arresto anomalo, sebbene elimini diversi oggetti che non sono sicuro di come estrarre: 'se let key = item [kSecAttrAccount] as? String, let value = item [kSecValueData] come? Dati {' –

0

Swift 3 versione con Xcode 9,1

func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { 

    var query: [String: Any] = [ 
     kSecClass as String : secClass, 
     kSecReturnData as String : kCFBooleanTrue, 
     kSecReturnAttributes as String : kCFBooleanTrue, 
     kSecReturnRef as String : kCFBooleanTrue, 
     kSecMatchLimit as String : kSecMatchLimitAll 
    ] 

    var result: AnyObject? 

    let lastResultCode = withUnsafeMutablePointer(to: &result) { 
     SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) 
    } 

    var values = [String:String]() 
    if lastResultCode == noErr { 
     let array = result as? Array<Dictionary<String, Any>> 

     for item in array! { 
      if let key = item[kSecAttrAccount as String] as? String, 
       let value = item[kSecValueData as String] as? Data { 
       values[key] = String(data: value, encoding:.utf8) 
      } 
     } 
    } 

    return values 
} 

può essere chiamato come:

debugPrint(getAllKeyChainItemsOfClass(kSecClassGenericPassword as String))