I am new to SwiftUI and Realm (using flexible sync), please excuse if it sounds like an elementary question I have location data saved in a MongoDB Atlas collection - Centre
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
}
}
and Coordinates are embedded objects where "x" is longitude and "y" is latitude
class Coordinates: EmbeddedObject, ObjectKeyIdentifiable {
@Persisted var x: Double?
@Persisted var y: Double?
}
I have created a Struct to conform to the requirements of MapAnnotation protocol as -
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)
}
}
I am trying to populate this struct from the data from Atlas collection My LocationView - not working
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)
}]
}
}
How do I populate the Struct with data from Centre collection?
Changed to (with no errors in 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()
}
}
now getting runtime error "Force unwrapping nil value"
with this function I am able to print out the results to console
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)
}
}
I get this printed out - [ACCv5.CustomAnnots(id: 67E9DADA-0BCC-4D30-8136-8B666881E82D, nameCentreLoc: "HO", descCentreLoc: "Head Office Artemis Cardiac Care Gurgaon", latitude: 28.438694893842058, longitude: 77.10845294294181)] [ACCv5.CustomAnnots(id: 26DC0C63-5A17-49C7-B4BF-FD3AA1ABF65E, nameCentreLoc: "Panipat", descCentreLoc: "Artemis Heart Centre at Ravindra Hospital", latitude: 29.388306713854682, longitude: 76.95889693063663)] [ACCv5.CustomAnnots(id: D3A70E58-6B65-4F5D-A398-3394B7FB04DF, nameCentreLoc: "Ranchi", descCentreLoc: "Artemis Heart Centre at Raj Hospital", latitude: 23.35731237118492, longitude: 85.32288933068195)]
But I am unable to display MapAnnotations with this -
@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)
})
Final code after Jay's suggestions
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)
})