繁体   English   中英

SwiftUI/ MapKit - 从 MongoDB Realm/ Atlas 集合填充一个 MapAnnotation 结构

[英]SwiftUI/ MapKit - Populate a MapAnnotation Struct from MongoDB Realm/ Atlas collection

我是 SwiftUI 和 Realm(使用灵活同步)的新手,如果这听起来像是一个基本问题,请原谅我将位置数据保存在 MongoDB 地图集 - 中心

class Centre: Object, ObjectKeyIdentifiable {
    @Persisted var _id: ObjectId = ObjectId.generate()
    @Persisted var centreName = ""
    @Persisted var centreDesc = ""
    @Persisted var centreLocation: Coordinates?
    
    override static func primaryKey() -> String? {
          return "_id"
      }
    convenience init(centreName: String, centreDesc: String, centreLocation: Coordinates) {
         self.init()
         self.centreName = centreName
         self.centreDesc = centreDesc
         self.centreLocation = centreLocation
     }
}

坐标是嵌入对象,其中“x”是经度,“y”是纬度

class Coordinates: EmbeddedObject, ObjectKeyIdentifiable {
    @Persisted var x: Double?
    @Persisted var y: Double?
}

我创建了一个 Struct 以符合 MapAnnotation 协议的要求,因为 -

struct CustomAnnots: Identifiable {
    let id: UUID
    var nameCentreLoc: String
    var descCentreLoc: String
    let latitude: Double
    let longitude: Double
    var coordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        }
    }

我正在尝试从 Atlas 集合中的数据填充此结构我的 LocationView - 不工作

import SwiftUI
import MapKit
import RealmSwift

struct LocationView: View {
    @Environment(\.realm) var realm
    @ObservedResults(Centre.self) var centres
    @ObservedRealmObject var centre: Centre
    @State private var nameCentreLoc = ""
    @State private var descCentreLoc = ""
    @State private var latitude = 0.0
    @State private var longitude = 0.0
    @State private var annots = []
    
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 24.681_858, longitude: 81.811_623),
        span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)
    )
    var body: some View {

        Map(coordinateRegion: $region, annotationItems: annots, annotationContent: { locations in
            MapPin(coordinate: locations.coordinate)
         })
        .onAppear {
            setSubscription()
           initData()
        }
       
        }
    
    
    private func setSubscription() {
        let subscriptions = realm.subscriptions
        subscriptions.write {
            if let currentSubscription = subscriptions.first(named: "all_centres") {
                currentSubscription.update(toType: Centre.self) { centre in
                    centre.centreName != ""
                }

            } else {
                subscriptions.append(QuerySubscription<Centre>(name: "all_centres") { centre in
                    centre.centreName != ""
                })
            }
        }
    }
    private func initData() {
        nameCentreLoc = centre.centreName
        descCentreLoc = centre.centreDesc
        latitude = (centre.centreLocation?.y)!
        longitude = (centre.centreLocation?.x)!
        let annots = [for centre in centres {
            CustomAnnots(id: UUID(), nameCentreLoc: nameCentreLoc, descCentreLoc: descCentreLoc, latitude: latitude, longitude: longitude)
        }]
    }
}

如何使用中心集合中的数据填充结构?

更改为(Xcode 中没有错误)-

    var body: some View {
        let annots = [CustomAnnots(id: UUID(), nameCentreLoc: centre.centreName, descCentreLoc: centre.centreDesc, latitude: (centre.centreLocation?.y)!, longitude: (centre.centreLocation?.x)!)]
        Map(coordinateRegion: $region, annotationItems: annots, annotationContent: { locations in
            MapPin(coordinate: locations.coordinate)
         })
        .onAppear {
            setSubscription()
        }
       
        }

现在收到运行时错误“强制解包 nil 值”

有了这个 function 我可以打印出结果到控制台

   func getLoc() {
        for centre in centres {
            var annots = [CustomAnnots.init(id: UUID(), nameCentreLoc: centre.centreName, descCentreLoc: centre.centreDesc, latitude: (centre.centreLocation?.y)!, longitude: (centre.centreLocation?.x)!)]
            print(annots)
        }
    }

我打印出来了 - [ACCv5.CustomAnnots(id: 67E9DADA-0BCC-4D30-8136-8B666881E82D, nameCentreLoc: "HO", descCentreLoc: "Head Office Artemis Cardiac Care Gurgaon", latitude: 28.438694893842058, longitude: 77.1084512814]294 [ ACCv5.CustomAnnots(id:26DC0C63-5A17-49C7-B4BF-FD3AA1ABF65E,nameCentreLoc:“Panipat”,descCentreLoc:“拉文德拉医院的阿耳忒弥斯心脏中心”,纬度:29.388306713854682,经度:76.95889693063663)] -6B65-4F5D-A398-3394B7FB04DF, nameCentreLoc: "Ranchi", descCentreLoc: "Artemis Heart Center at Raj Hospital", latitude: 23.35731237118492, longitude: 85.32288933068195)]

但是我无法用这个显示 MapAnnotations -

    @Environment(\.realm) var realm
    @ObservedResults(Centre.self) var centres
    @State public var annots: [CustomAnnots]
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 24.681_858, longitude: 81.811_623),
        span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)
    )
    var body: some View {
        ForEach (centres) { centre in
            var annots = [CustomAnnots.init(id: UUID(), nameCentreLoc: centre.centreName, descCentreLoc: centre.centreDesc, latitude: (centre.centreLocation?.y)!, longitude: (centre.centreLocation?.x)!)]
        }
       // Text("\(annots.count)")
        Map(coordinateRegion: $region, annotationItems: annots, annotationContent: { locations in
            MapMarker(coordinate: locations.coordinate)
         })

Jay 建议后的最终代码

class Centre: Object, ObjectKeyIdentifiable {
    @Persisted var _id: ObjectId = ObjectId.generate()
    @Persisted var centreName = ""
    @Persisted var centreDesc = ""
    @Persisted var centreLocation: Coordinates?
    
    override static func primaryKey() -> String? {
          return "_id"
      }
  
    convenience init(centreName: String, centreDesc: String, x: Double, y: Double) {
         self.init()
         self.centreName = centreName
         self.centreDesc = centreDesc
         self.centreLocation?.x = x
         self.centreLocation?.y = y
     }
    var coordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: (centreLocation?.y)!, longitude: (centreLocation?.x)!)
        }
}


 Map(coordinateRegion: $region, annotationItems: centres, annotationContent: { centre in
            MapMarker(coordinate: centre.coordinate)
         })

简化可能会产生更精简的解决方案。

如果目标是从 Realm 对象填充 map,那么我认为您走在正确的轨道上,但是移动部件太多了 - 让我们减少代码。 如果我误解了这个问题,请告诉我..

这是一些伪代码:

从包含数据的 Realm object 开始。 请注意,我们不需要主键,因为我们为此使用了 ObjectId。 这个 object 具有跟踪 map 上的引脚所需的一切,它可以观察变化并返回一个计算的变量,其中包含要在 map 本身上使用的 MapAnnotation,基于 object 中的数据

class Centre: Object, ObjectKeyIdentifiable {
    @Persisted var _id: ObjectId = ObjectId.generate()
    @Persisted var centreName = ""
    @Persisted var centreDesc = ""
    @Persisted var x: Double!
    @Persisted var y: Double!

    var mapAnno: MapAnnotation {
        //build the map annotation from the above properties
        return //return the map annotation
    }

    convenience init(centreName: String, centreDesc: String, x: Double, y: Double) {
        self.init()
        self.centreName = centreName
        self.centreDesc = centreDesc
        self.x = x
        self.y = y
     }
}

然后在视图中 - 加载所有中心并迭代它们,从每个中心检索 MapAnnotation

@ObservedResults(Centre.self) var centres //loads all of the centrs

var body: some View {
        ForEach (centres) { centre in
             let mapAnnotation = centre.mapAnno
             //add the annotation to the map

请注意,这种模式也很常见

Map(coordinateRegion: $region,
    showsUserLocation: true,
    annotationItems: centres) { center in
                    MapAnnotation(coordinate: //get coords from centre)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM