| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- //
- // MapAmapGeneralProcessing.swift
- // map_amap_ios
- //
- // Created by 诺诺诺的言 on 2025/7/22.
- //
- import Foundation
- import MapKit
- import ObjectiveC
- extension Decodable {
- static func fromJson(json: Any) -> Self? {
- do {
- let data = try JSONSerialization.data(withJSONObject: json, options: [])
- return try JSONDecoder().decode(Self.self, from: data)
- } catch {
- print(error.localizedDescription)
- return nil
- }
- }
- }
- 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
- }
- struct ATMapPadding: Codable {
- var top: CGFloat
- var left: CGFloat
- var bottom: CGFloat
- var right: CGFloat
- var padding: UIEdgeInsets {
- return UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
- }
- }
- // 定义关联对象的键
- private var associatedLineIdKey = "associatedLineIdKey"
- private var associatedLineTypeKey = "associatedLineTypeKey"
- private var associatedColorKey = "associatedColorKey"
- private var associatedWidthKey = "associatedWidthKey"
- extension MKPolyline {
- // 关联 lineId 属性
- var associatedLineId: String? {
- get {
- return objc_getAssociatedObject(self, &associatedLineIdKey) as? String
- }
- set {
- objc_setAssociatedObject(self, &associatedLineIdKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
-
- // 关联 lineType 属性
- var associatedLineType: String? {
- get {
- return objc_getAssociatedObject(self, &associatedLineTypeKey) as? String
- }
- set {
- objc_setAssociatedObject(self, &associatedLineTypeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
-
- // 关联 color 属性
- var associatedColor: String? {
- get {
- return objc_getAssociatedObject(self, &associatedColorKey) as? String
- }
- set {
- objc_setAssociatedObject(self, &associatedColorKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
-
- // 关联 width 属性
- var associatedWidth: Double? {
- get {
- return objc_getAssociatedObject(self, &associatedWidthKey) as? Double
- }
- set {
- objc_setAssociatedObject(self, &associatedWidthKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
- }
- class ATMapPolyline: NSObject, Codable {
- var id: String = UUID().uuidString
- var lineId: String // 新增:用于记录的线ID
- var lineType: String // 新增:用于记录线的样式 normal error selected color
- var points: [CLLocationCoordinate2D]
- var mapPadding: ATMapPadding?
- var color : String ///轨迹的颜色
- var width: Double /// 轨迹的宽度
-
- var polyline: MKPolyline {
- return MKPolyline(coordinates: points, count: points.count)
- }
- enum CodingKeys: String, CodingKey {
- case lineId, lineType, points, mapPadding,color,width
- }
-
- required init(from decoder: Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
-
- if container.contains(.lineId) {
- lineId = try container.decodeIfPresent(String.self, forKey: .lineId) ?? ""
- } else {
- lineId = ""
- }
- if container.contains(.lineType) {
- lineType = try container.decodeIfPresent(String.self, forKey: .lineType) ?? ""
- } else {
- lineType = "";
- }
- if container.contains(.points) {
- points = try container.decodeIfPresent([CLLocationCoordinate2D].self, forKey: .points) ?? [CLLocationCoordinate2D]()
- } else {
- points = [CLLocationCoordinate2D]()
- }
- if container.contains(.color) {
- color = try container.decodeIfPresent(String.self, forKey: .color) ?? ""
- } else {
- color = ""
- }
- if container.contains(.width) {
- width = try container.decodeIfPresent(Double.self, forKey: .width) ?? 0
- } else {
- width = 0
- }
- if container.contains(.mapPadding) {
- mapPadding = try container.decodeIfPresent(ATMapPadding.self, forKey: .mapPadding) ?? ATMapPadding(top: 0, left: 0, bottom: 0, right: 0)
- } else {
- mapPadding = ATMapPadding(top: 0, left: 0, bottom: 0, right: 0)
- }
- }
-
- func encode(to encoder: Encoder) throws {
- var container = encoder.container(keyedBy: CodingKeys.self)
- try container.encode(lineId, forKey: .lineId)
- try container.encode(lineType, forKey: .lineType)
- try container.encode(points, forKey: .points)
- try container.encodeIfPresent(mapPadding, forKey: .mapPadding)
- }
-
- // 初始化方法
- init(lineId: String, lineType: String, points: [CLLocationCoordinate2D], mapPadding: ATMapPadding? = nil,color : String,width : Double) {
- self.lineId = lineId
- self.lineType = lineType
- self.points = points
- self.mapPadding = mapPadding
- self.color = color
- self.width = width
- super.init()
- }
- }
- class ATMapMarker: NSObject, Codable {
- var id: String
- var markerId: String
- var markerName: String?
- var customAvatarUrl : String?
- var latitude: CGFloat
- var longitude: CGFloat
- var isSelected: Bool
- var markerType: any MapMarkerSupportType
- var tags: [String : String]?
- init(id: String, markerId: String,markerName: String?, customAvatarUrl: String?,location: CLLocationCoordinate2D, markerType: any MapMarkerSupportType, isSelected: Bool = false,tags: [String : String]?) {
- self.id = id
- self.markerId = markerId
- self.markerName = markerName
- self.customAvatarUrl = customAvatarUrl
- self.latitude = location.latitude
- self.longitude = location.longitude
- self.markerType = markerType
- self.isSelected = isSelected
- self.tags = tags
- }
-
- func update(coordinate: CLLocationCoordinate2D, name: String? = nil, isSelect: Bool) {
- self.latitude = coordinate.latitude
- self.longitude = coordinate.longitude
- self.markerName = name
- self.isSelected = isSelect
- }
- enum CodingKeys: String, CodingKey {
- case id,markerId,markerName,customAvatarUrl, latitude, longitude, isSelected, markerType,tags
- }
- required init(from decoder: Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
- id = try container.decode(String.self, forKey: .id)
- if id.isEmpty {
- id = "user_location"
- }
- if container.contains(.markerName) {
- markerName = try container.decodeIfPresent(String.self, forKey: .markerName) ?? ""
- } else {
- markerName = ""
- }
- if container.contains(.customAvatarUrl) {
- customAvatarUrl = try container.decodeIfPresent(String.self, forKey: .customAvatarUrl) ?? ""
- } else {
- customAvatarUrl = ""
- }
-
- if container.contains(.latitude) {
- latitude = try container.decodeIfPresent(CGFloat.self, forKey: .latitude) ?? 0
- } else {
- latitude = 0
- }
- if container.contains(.longitude) {
- longitude = try container.decodeIfPresent(CGFloat.self, forKey: .longitude) ?? 0
- } else {
- longitude = 0
- }
- if container.contains(.isSelected) {
- isSelected = try container.decodeIfPresent(Bool.self, forKey: .isSelected) ?? false
- } else {
- isSelected = false
- }
-
-
- // 使用工厂方法创建正确类型的markerType
- if container.contains(.markerType) {
- let rawValue = try container.decodeIfPresent(Int.self, forKey: .markerType) ?? 1
- markerType = MarkerTypeFactory.markerType(from: rawValue)
- } else {
- markerType = MarkerTypeFactory.markerType(from: 1)
- }
-
- ///气泡内容
- // 处理tags为空的情况
- if container.contains(.tags) {
- tags = try container.decodeIfPresent([String: String].self, forKey: .tags) ?? [:]
- } else {
- tags = [:] // 默认为空字典
- }
- if container.contains(.markerId) {
- markerId = try container.decodeIfPresent(String.self, forKey: .markerId) ?? ""
- } else {
- markerId = ""
- }
- }
- 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(customAvatarUrl, forKey: .customAvatarUrl)
- 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)
- try container.encode(tags, forKey: .tags)
- try container.encode(markerId, forKey: .markerId)
- }
- }
- 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)
- }
- }
- class ATMapLocation: NSObject, Codable {
- var latitude: CGFloat?
- var longitude: CGFloat?
- var address: String?
- var errorCode: Int = 0
- var time: Int?
- var bearing: CGFloat?
- var speed: CGFloat?
- init(latitude: CGFloat? = nil, longitude: CGFloat? = nil, address: String? = nil, time: Int? = nil, bearing: CGFloat? = nil, speed: CGFloat? = nil) {
- self.latitude = latitude
- self.longitude = longitude
- self.address = address
- self.time = time
- self.bearing = bearing
- self.speed = speed
- super.init()
- }
- static func fromLocation(location: CLLocation) -> ATMapLocation {
- return ATMapLocation(
- latitude: CGFloat(location.coordinate.latitude),
- longitude: CGFloat(location.coordinate.longitude),
- address: nil,
- time: Int(location.timestamp.timeIntervalSince1970 * 1000),
- bearing: CGFloat(location.course),
- speed: CGFloat(location.speed)
- )
- }
- }
|