// // Models.swift // Runner // // Created by Groot on 2025/5/9. // import Foundation import MapKit extension Decodable { static func fromJson(json: [String: Any]) -> Self? { guard let data = try? JSONSerialization.data(withJSONObject: json, options: []) else { return nil } return try? JSONDecoder().decode(Self.self, from: data) } } extension Encodable { func toJson() -> [String: Any] { guard let data = try? JSONEncoder().encode(self) else { return [:] } return try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] } } struct ATMapCameraPosition: Codable { var latitude: CGFloat var longitude: CGFloat // 地图缩放比例,对应span var zoom: CGFloat } class ATMapPolyline: NSObject, Codable { var id: String = UUID().uuidString var points: [CLLocationCoordinate2D] var polyline: MKPolyline { return MKPolyline(coordinates: points, count: points.count) } init(points: [CLLocationCoordinate2D]) { self.points = points } } class ATMapMarker: NSObject, Codable { var id: String var markerName: String var latitude: CGFloat var longitude: CGFloat var isSelected: Bool var markerType: any MapMarkerSupportType enum CodingKeys: String, CodingKey { case id, markerName, latitude, longitude, isSelected, markerType } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(String.self, forKey: .id) markerName = try container.decode(String.self, forKey: .markerName) latitude = try container.decode(CGFloat.self, forKey: .latitude) longitude = try container.decode(CGFloat.self, forKey: .longitude) isSelected = try container.decode(Bool.self, forKey: .isSelected) // 使用工厂方法创建正确类型的markerType let rawValue = try container.decode(Int.self, forKey: .markerType) markerType = MarkerTypeFactory.markerType(from: rawValue) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(markerName, forKey: .markerName) try container.encode(latitude, forKey: .latitude) try container.encode(longitude, forKey: .longitude) try container.encode(isSelected, forKey: .isSelected) try container.encode(markerType.rawValue, forKey: .markerType) } } extension ATMapMarker: MKAnnotation { var coordinate: CLLocationCoordinate2D { return CLLocationCoordinate2D(latitude: latitude, longitude: longitude) } } extension CLLocationCoordinate2D: Codable { enum CodingKeys: String, CodingKey { case latitude case longitude } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let latitude = try container.decode(Double.self, forKey: .latitude) let longitude = try container.decode(Double.self, forKey: .longitude) self.init(latitude: latitude, longitude: longitude) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(latitude, forKey: .latitude) try container.encode(longitude, forKey: .longitude) } }