Jojodmo Jojodmo - 2 months ago 36
Swift Question

UnsafeMutablePointer<CFTypeRef> in Swift 3

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. Bases 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?

Answer

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)