[英]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.