UnsafeMutablePointer<CFTypeRef> en Swift 3
swift3 core-foundation (2)
Estoy intentando llamar a SecItemCopyMatching
en mi clase de utilidad de llavero para obtener datos del llavero, pero estoy teniendo un problema al obtener el argumento de result
, UnsafeMutablePointer<CFTypeRef?>
.
La declaración original (en Swift 2, antes de migrar a Swift 3) era
// query is a dictionary of [String : AnyObject]
var result: Data?
let status = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
Pero en Swift 3, ahora se requiere que llame a .withMemoryRebound
para ver la memoria. Según lo que Xcode te dice que hagas, probé esto
var result: Data?
let status = withUnsafeMutablePointer(to: &result){
$0.withMemoryRebound(to: Data.self, capacity: 1){
SecItemCopyMatching(query as CFDictionary, UnsafePointer($0))
}
}
Sin embargo, al hacer esto, me sale un error
No se puede convertir el valor del tipo ''
UnsafePointer<_>
'' al tipo de argumento esperado ''UnsafeMutablePointer<CFTypeRef?>?
''
Entonces, traté de usar CFTypeRef
lugar de Data
var result: CFTypeRef?
let status = withUnsafeMutablePointer(to: &result){
$0.withMemoryRebound(to: CFTypeRef.self, capacity: 1){
SecItemCopyMatching(query as CFDictionary, UnsafePointer($0))
}
}
Reemplazar UnsafePointer($0)
con simplemente $0
resulta en el mismo mensaje de error.
¿Cómo puedo obtener un UnsafeMutablePointer<CFTypeRef?>
Para obtener datos de keychain?
En su caso, no necesita usar withMemoryRebound
o withUnsafeMutablePointer(to:)
.
En cambio, puedes usar
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
if status == noErr, let data = result as? Data {
//use data...
}
Generalmente, cuando necesita pasar un UnsafeMutablePointer<T>
a una función, declare una variable de tipo T
y páselo como un argumento &variable
inout. En su caso, T
es CFTypeRef?
, y en Swift 3, CFTypeRef
es solo una tipografía de AnyObject
.
Incluso en Swift 2.2, no era necesario usar withUnsafeMutablePointer
var result: AnyObject?
let status = SecItemCopyMatching(query, &result)
El mensaje de error es algo engañoso: ¿el problema real es que el result
tiene que ser un AnyObject?
- withMemoryRebound
no necesita ser utilizado.
var result: AnyObject?
let status = withUnsafeMutablePointer(to: &result){
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
Funciona de la manera esperada y obtiene el resultado correcto del llavero: solo debe transferirse a Data
. De hecho, withUnsafeMutablePointer
ni siquiera tiene que ser utilizado .
Entonces, mi nuevo código es
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
}