web-dev-qa-db-ja.com

UnsafeMutablePointer in Swift Obj-Cの適切なサイズのC配列の代わりとして

サイズのC配列を取るために使用されたSwiftの関数とどのように対話できますか?

C APISとの相互作用 を読み通しましたが、それでもこれを理解できません。

func getCoordinates(_ coords:UnsafeMutablePointer<CLLocationCoordinate2D>,range range: NSRange)のc​​oordsパラメータのドキュメントには、「入力時に、必要な数の座標を保持するのに十分な大きさの構造体のC配列を指定する必要があります。出力時に、この構造体には要求された座標データが含まれます。」

最近、いくつか試してみました。

var coordinates: UnsafeMutablePointer<CLLocationCoordinate2D> = nil
polyline.getCoordinates(&coordinates, range: NSMakeRange(0, polyline.pointCount))

次のようなものを使用する必要がありますか?

var coordinates = UnsafeMutablePointer<CLLocationCoordinate2D>(calloc(1, UInt(polyline.pointCount)))

ここで髪を抜く...何か考えはありますか?

18
Andrew Robinson

通常、必要なタイプの配列をin-outパラメータとして渡すことができます。

_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))
_
50
Nate Cook

@Nate Cookのすばらしい答えの拡張ラッパーは、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
        }
    }
}
0
DazChong