可编码 MKPolygon?
Codable MKPolygon?
好的,请耐心等待。
我有一个坐标数据库,我正在尝试提取该数据,将其解码为也符合 MKPolygon 的可编码 class,然后才能将该多边形添加到地图视图中。
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)
encoding/decoding 是在 CodableFirebase CocoaPod 的帮助下完成的,它成功地对其进行了编码,但现在我该如何添加实际坐标来创建多边形?
我不建议继承 MKPolygon
。坦率地说,我根本不建议创建 CustomPolygon
和 Coordinate
。无需引入反映原生 MKPolygon
和 CLLocationCoordinate2D
类型的类型。
与其尝试创建一个可编码的 MKPolygon
,我可能会建议创建一个仅表示坐标集合的 Codable
类型,它对纬度和经度数组进行编码。
但首先,让我们考虑一个 JSON 结构,一个坐标数组:
[
{"longitude":37.785834, "latitude":-122.406417},
{"longitude":37.246878, "latitude":-122.245676},
...
]
因此,我将创建一个 encodes/decodes 类型,如 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
轻松创建 MKPolygon
和 MKPolyline
,反之亦然:
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
。然后您可以使用 polygon
或 polyline
计算属性来构建适当的 MKOverlay
类型,然后您可以将其添加到地图中。
并且由于 Coordinates
是 Codable
,您现在可以在自己的 Codable
类型中使用此类型,例如:
struct RegionOfInterest: Codable {
let name: String
let coordinates: Coordinates
}
好的,请耐心等待。 我有一个坐标数据库,我正在尝试提取该数据,将其解码为也符合 MKPolygon 的可编码 class,然后才能将该多边形添加到地图视图中。
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)
encoding/decoding 是在 CodableFirebase CocoaPod 的帮助下完成的,它成功地对其进行了编码,但现在我该如何添加实际坐标来创建多边形?
我不建议继承 MKPolygon
。坦率地说,我根本不建议创建 CustomPolygon
和 Coordinate
。无需引入反映原生 MKPolygon
和 CLLocationCoordinate2D
类型的类型。
与其尝试创建一个可编码的 MKPolygon
,我可能会建议创建一个仅表示坐标集合的 Codable
类型,它对纬度和经度数组进行编码。
但首先,让我们考虑一个 JSON 结构,一个坐标数组:
[
{"longitude":37.785834, "latitude":-122.406417},
{"longitude":37.246878, "latitude":-122.245676},
...
]
因此,我将创建一个 encodes/decodes 类型,如 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
轻松创建 MKPolygon
和 MKPolyline
,反之亦然:
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
。然后您可以使用 polygon
或 polyline
计算属性来构建适当的 MKOverlay
类型,然后您可以将其添加到地图中。
并且由于 Coordinates
是 Codable
,您现在可以在自己的 Codable
类型中使用此类型,例如:
struct RegionOfInterest: Codable {
let name: String
let coordinates: Coordinates
}