【问题标题】:SwiftUI/ MapKit - Populate a MapAnnotation Struct from MongoDB Realm/ Atlas collectionSwiftUI/ MapKit - 从 MongoDB 领域/ Atlas 集合填充 MapAnnotation 结构
【发布时间】:2022-06-11 02:58:49
【问题描述】:

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

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?
}

我创建了一个符合 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)
        }]
    }
}

如何使用 Center 集合中的数据填充 Struct?

更改为(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 值”

使用此功能,我可以将结果打印到控制台

   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”,纬度:28.438694893842058,经度:77.10845294294181) [ACCv5.CustomAnnots(id: 26DC0C63-5A17-49C7-B4BF-FD3AA1ABF65E, nameCentreLoc: "Panipat", descCentreLoc: "Artemis Heart Center at Ravindra Hospital", 纬度: 29.388306713854682, 经度: 76.95889693063663)] [ACCv5.CustomAnnots(id: D3A70E58-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)
         })

【问题讨论】:

  • 欢迎来到 SO。告诉我们一些事情 - 不起作用 - 是模糊的。有什么不好的?哪条线路没有按预期工作?你做了哪些故障排除?此外,您似乎正在处理大量重复数据。最后,为什么不将数据存储在 Realm 对象中并拥有一个直接返回 CustomAnnot 对象的函数呢?另外,请注意MapAnnotation Protocol Documentation 中的这一点不要创建符合此协议的类型。请改用 MapAnnotation 框架。
  • 感谢您的回复,杰。 “let annots = [for center...”这一行抛出“容器文字中的预期表达式”和“annotationItems:annots”初始“在范围内找不到它。然后我创建了一个空数组”@State private var annots = [ ]”,错误是“协议'Any'作为一种类型不能符合'Identifiable'”
  • 是的 - 我希望这些错误基于代码。根据描述,您尝试执行的操作似乎过于复杂。在这个用例中不需要协议,您的对象实际上只是重复数据。我认为您可以使用一个返回所需 MapAnnotation 数据的对象来完成整个任务。
  • 我已经简化了代码并设法检索符合结构的数据但仍然无法显示 MapAnnotations - 更新的代码在上面

标签: swiftui realm mongodb-atlas mapkitannotation


【解决方案1】:

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

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

这是一些伪代码:

从包含数据的领域对象开始。请注意,我们不需要主键,因为我们为此使用了 ObjectId。该对象具有在地图上跟踪图钉所需的一切,可以观察它的变化并根据对象中的数据返回一个包含要在地图本身上使用的 MapAnnotation 的计算 var

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多