UnsafeMutablePointer в быстрой замене для C-массива с соответствующим размером C в Obj-C
Как я могу взаимодействовать с функциями в swift, которые используются для получения массивов C размера?
Я прочитал Взаимодействие с C APIS и до сих пор не могу понять этого.
В документации для параметра coords параметра func getCoordinates(_ coords:UnsafeMutablePointer<CLLocationCoordinate2D>,range range: NSRange)
указано: "На входе вы должны предоставить массив C структур, достаточно больших, чтобы удерживать требуемое количество координат. На выходе эта структура содержит запрошенные координаты".
Я пробовал несколько вещей, совсем недавно:
var coordinates: UnsafeMutablePointer<CLLocationCoordinate2D> = nil
polyline.getCoordinates(&coordinates, range: NSMakeRange(0, polyline.pointCount))
Должен ли я использовать что-то вроде:
var coordinates = UnsafeMutablePointer<CLLocationCoordinate2D>(calloc(1, UInt(polyline.pointCount)))
Вытащить мои волосы здесь... любые мысли?
Ответы
Ответ 1
Обычно вы можете просто передать массив требуемого типа в качестве параметра in-out, aka
var coords: [CLLocationCoordinate2D] = []
polyline.getCoordinates(&coords, range: NSMakeRange(0, polyline.pointCount))
но эта документация заставляет ее казаться плохой идеей! К счастью, UnsafeMutablePointer
предоставляет статический метод alloc(num: Int)
, поэтому вы можете вызвать getCoordinates()
следующим образом:
var coordsPointer = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(polyline.pointCount)
polyline.getCoordinates(coordsPointer, range: NSMakeRange(0, polyline.pointCount))
Чтобы получить фактические объекты CLLocationCoordinate2D
из изменяемого указателя, вы должны просто выполнить цикл:
var coords: [CLLocationCoordinate2D] = []
for i in 0..<polyline.pointCount {
coords.append(coordsPointer[i])
}
И так как вы не хотите утечки памяти, закончите так:
coordsPointer.dealloc(polyline.pointCount)
Только что вспомнил Array
имеет метод экземпляра reserveCapacity()
, поэтому гораздо более простая (и, вероятно, более безопасная) версия этого будет:
var coords: [CLLocationCoordinate2D] = []
coords.reserveCapacity(polyline.pointCount)
polyline.getCoordinates(&coords, range: NSMakeRange(0, polyline.pointCount))
Ответ 2
расшифровка оболочки для @Nate Cook awesome answer, не может заставить версию reserveCapacity()
работать, она возвращает возвращаемый пустой объект.
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
}
}
}