【问题标题】:Codable MKPolygon?可编码的 MKPolygon?
【发布时间】:2021-02-13 09:08:00
【问题描述】:

好的,请耐心等待。 我有一个坐标数据库,我正在尝试将这些数据拉下来,将其解码为一个也符合 MKPolygon 的可编码类,然后就可以将该多边形添加到地图视图中。

class CustomPolygon : MKPolygon, Codable {

    var perimeter : [Coordinate]!

}
struct Coordinate : Codable {
    let Latitude : CLLocationDegrees
    let Longitude : CLLocationDegrees
    
    func getCoord() -> CLLocationCoordinate2D {
        return CLLocationCoordinate2D(latitude: self.Latitude, longitude: self.Longitude)
    }
}

我从数据库中解码时的重要代码是这样的:

let polygon = try! FirestoreDecoder().decode(CustomPolygon.self, from: data)

编码/解码是在 CodableFirebase CocoaPod 的帮助下进行的,它成功编码,但现在我如何添加实际坐标来创建多边形?

【问题讨论】:

  • 我不认为子类化MKPolygon 是正确的方法。我会创建一个 Codable 结构体,其函数或计算属性使用坐标返回 MKPolygon 的实例。

标签: ios swift firebase mapkit codable


【解决方案1】:

我不建议子类化MKPolygon。坦率地说,我根本不建议创建 CustomPolygonCoordinate。无需引入镜像原生 MKPolygonCLLocationCoordinate2D 类型的类型。

与其尝试创建可编码的MKPolygon,不如建议创建一个仅表示坐标集合的Codable 类型,该类型对纬度和经度数组进行编码。

但首先,让我们考虑一个 JSON 结构,一个坐标数组:

[
    {"longitude":37.785834, "latitude":-122.406417},
    {"longitude":37.246878, "latitude":-122.245676},
    ...
]

因此,我将创建一个编码/解码类型,如Encoding and Decoding Custom Types 的“手动编码和解码”部分所述:

struct Coordinates: Codable {
    var coordinates: [CLLocationCoordinate2D] = []

    // MARK: Codable

    enum CodingKeys: String, CodingKey {
        case latitude, longitude
    }

    init(from decoder: Decoder) throws {
        var container = try decoder.unkeyedContainer()

        while !container.isAtEnd {
            let subcontainer = try container.nestedContainer(keyedBy: CodingKeys.self)
            let latitude = try subcontainer.decode(CLLocationDegrees.self, forKey: .latitude)
            let longitude = try subcontainer.decode(CLLocationDegrees.self, forKey: .longitude)
            coordinates.append(CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()

        for value in coordinates {
            var subcontainer = container.nestedContainer(keyedBy: CodingKeys.self)
            try subcontainer.encode(value.latitude, forKey: .latitude)
            try subcontainer.encode(value.longitude, forKey: .longitude)
        }
    }
}

我还可以创建一些方便的方法来轻松地从Coordinates 创建MKPolygonMKPolyline,反之亦然:

extension Coordinates {
    init(from polygon: MKPolygon) {
        self.polygon = polygon
    }

    init(from polyline: MKPolyline) {
        self.polyline = polyline
    }

    var polygon: MKPolygon {
        get { MKPolygon(coordinates: coordinates, count: coordinates.count) }
        set { updateCoordinates(from: newValue) }
    }

    var polyline: MKPolyline {
        get { MKPolyline(coordinates: coordinates, count: coordinates.count) }
        set { updateCoordinates(from: newValue) }
    }

    private mutating func updateCoordinates(from shape: MKMultiPoint) {
        let pointCount = shape.pointCount
        coordinates = .init(repeating: kCLLocationCoordinate2DInvalid, count: pointCount)
        shape.getCoordinates(&coordinates, range: NSRange(location: 0, length: pointCount))
    }
}

extension MKPolyline {
    var coordinates: Coordinates { Coordinates(from: self) }
}

extension MKPolygon {
    var coordinates: Coordinates { Coordinates(from: self) }
}

那么,如果你想编码一个多边形的坐标:

let coordinates = polygon.coordinates            // if you need to extract the `Coordinates` collection from the `MKPolygon`
let data = try JSONEncoder().encode(coordinates)

或者,如果您想解码坐标并从中创建一个MKPolygon

let coordinates = try JSONDecoder().decode(Coordinates.self, from: data)
let polygon = coordinates.polygon                // if you want to add a `MKPolygon` represented by this collection of `Coordinates`

但想法是,您的模型对象将是 Coordinates 类型(即 CLLocationCoordinate2d 的集合),即 Codable。然后,您可以使用 polygonpolyline 计算属性来构建适当的 MKOverlay 类型,然后您可以将其添加到地图中。

因为CoordinatesCodable,你现在可以在你自己的Codable 类型中使用这个类型,例如:

struct RegionOfInterest: Codable {
    let name: String
    let coordinates: Coordinates
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多