objective - UnsafeMutablePointer en swift como reemplazo para una matriz C del tamaño adecuado en Obj-C
swift to objective c (2)
Normalmente, solo puede pasar una matriz del tipo requerido como un parámetro de entrada-salida, también conocido como
var coords: [CLLocationCoordinate2D] = []
polyline.getCoordinates(&coords, range: NSMakeRange(0, polyline.pointCount))
¡Pero esa documentación hace que parezca una mala idea! Afortunadamente, UnsafeMutablePointer
proporciona un alloc(num: Int)
estática alloc(num: Int)
, por lo que puede llamar a getCoordinates()
siguiente manera:
var coordsPointer = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(polyline.pointCount)
polyline.getCoordinates(coordsPointer, range: NSMakeRange(0, polyline.pointCount))
Para obtener los objetos CLLocationCoordinate2D
reales fuera del puntero mutable, debería poder simplemente realizar un bucle a través de:
var coords: [CLLocationCoordinate2D] = []
for i in 0..<polyline.pointCount {
coords.append(coordsPointer[i])
}
Y como no quieres una pérdida de memoria, termina así:
coordsPointer.dealloc(polyline.pointCount)
Acabo de recordar que Array
tiene un método de instancia reserveCapacity()
, por lo que una versión mucho más simple (y probablemente más segura) sería:
var coords: [CLLocationCoordinate2D] = []
coords.reserveCapacity(polyline.pointCount)
polyline.getCoordinates(&coords, range: NSMakeRange(0, polyline.pointCount))
¿Cómo puedo interactuar con las funciones de Swift que solían tomar matrices de tamaño C?
Leí Interactuar con C APIS y todavía no puedo resolver esto.
La documentación para el parámetro coords de func getCoordinates(_ coords:UnsafeMutablePointer<CLLocationCoordinate2D>,range range: NSRange)
indica: "En la entrada, debe proporcionar un conjunto de C de estructuras lo suficientemente grande como para contener el número deseado de coordenadas. En la salida, esta estructura contiene los datos de coordenadas solicitados ".
Probé varias cosas, la más reciente:
var coordinates: UnsafeMutablePointer<CLLocationCoordinate2D> = nil
polyline.getCoordinates(&coordinates, range: NSMakeRange(0, polyline.pointCount))
¿Tendría que usar algo como:
var coordinates = UnsafeMutablePointer<CLLocationCoordinate2D>(calloc(1, UInt(polyline.pointCount)))
Sacándome el pelo aquí ... ¿alguna idea?
la envoltura de extensión para la asombrosa respuesta de @Nate Cook, no puede hacer que reserveCapacity()
versión reserveCapacity()
, sigue devolviendo el objeto vacío.
import MapKit
extension MKPolyline {
var coordinates: [CLLocationCoordinate2D] {
get {
let coordsPointer = UnsafeMutablePointer<CLLocationCoordinate2D>.allocate(capacity: pointCount)
var coords: [CLLocationCoordinate2D] = []
for i in 0..<pointCount {
coords.append(coordsPointer[i])
}
coordsPointer.deallocate(capacity: pointCount)
return coords
}
}
}