问题
I'm attempting to call SecItemCopyMatching
in my keychain utility class in order to get data out of the keychain, yet I'm running into a problem with getting the result
argument, UnsafeMutablePointer<CFTypeRef?>
.
The original statement (in Swift 2, before migrating to Swift 3) was
// query is a dictionary of [String : AnyObject]
var result: Data?
let status = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
But in Swift 3, you are now required to call .withMemoryRebound
in order to view memory. Based on what Xcode tells you to do, I tried this
var result: Data?
let status = withUnsafeMutablePointer(to: &result){
$0.withMemoryRebound(to: Data.self, capacity: 1){
SecItemCopyMatching(query as CFDictionary, UnsafePointer($0))
}
}
Yet doing this, I get an error
Cannot convert value of type '
UnsafePointer<_>
' to expected argument type 'UnsafeMutablePointer<CFTypeRef?>?
'
So, I tried using CFTypeRef
instead of Data
var result: CFTypeRef?
let status = withUnsafeMutablePointer(to: &result){
$0.withMemoryRebound(to: CFTypeRef.self, capacity: 1){
SecItemCopyMatching(query as CFDictionary, UnsafePointer($0))
}
}
Replacing UnsafePointer($0)
with simply $0
results in the same error message.
How can I get an UnsafeMutablePointer<CFTypeRef?>
for getting data from keychain?
回答1:
In your case, you do not need to use withMemoryRebound
or withUnsafeMutablePointer(to:)
.
Instead, you can just use
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
if status == noErr, let data = result as? Data {
//use data...
}
Generally, when you need to pass an UnsafeMutablePointer<T>
to a function, declare a variable of type T
and pass it as an inout argument &variable
. In your case, T
is CFTypeRef?
, and in Swift 3, CFTypeRef
is just a typealias of AnyObject
.
Even in Swift 2.2, you did not need to use withUnsafeMutablePointer
var result: AnyObject?
let status = SecItemCopyMatching(query, &result)
回答2:
The error message is somewhat misleading - the actual problem is that result
has to be an AnyObject?
- withMemoryRebound
doesn't need to be used.
var result: AnyObject?
let status = withUnsafeMutablePointer(to: &result){
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
Works as expected and gets the correct result from keychain - it just needs to be casted to Data
. In fact, withUnsafeMutablePointer doesn't even have to be used.
So, my new code is
var query: [String : AnyObject] = [:]
//set up the query
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
var data: Data?
if status == noErr{
data = result as? Data
}
来源:https://stackoverflow.com/questions/39441894/unsafemutablepointercftyperef-in-swift-3