To construct a query, we need to represent it as a CFDictionary
. You may also use NSDictionary
in Objective-C or Dictionary
in Swift and cast to CFDictionary
.
We need a class key:
var dict = [String : AnyObject]()
dict[kSecClass as String] = kSecClassGenericPassword
Next, we can specify attributes to narrow down our search:
// Label
dict[kSecAttrLabel as String] = "com.me.myapp.myaccountpassword" as CFString
// Username
dict[kSecAttrAccount as String] = "My Name" as CFString
// Service name
dict[kSecAttrService as String] = "MyService" as CFString
We can also specify special search modifier keys described here.
Finally, we need to say how we'd like our data returned. Below, we'll request that just the private password itself be returned as a CFData
object:
dict[kSecReturnData as String] = kCFBooleanTrue
Now, let's search:
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(dict as CFDictionary, UnsafeMutablePointer($0))
}
// Don't keep this in memory for long!!
let password = String(data: queryResult as! Data, encoding: .utf8)!
Here, SecItemCopyMatching
takes in a query dictionary and a pointer to where you'd like the result to go. It returns an OSStatus
with a result codes. Here are the possibilities.