'Show multiple users' location stored in a database on a map with SwiftUI and Firebase
As said in the title, I would like to show the location of my users on a map in my app. I would like something like Snapshat map :
I used SwiftUI and Firebase.
Here is what I have done so far :
import SwiftUI
import Firebase
import CoreLocation
import MapKit
struct mapTimelineView: View {
@StateObject private var locationViewModel = LocationViewModel.shared
@State private var showNewPostView = false
@ObservedObject var viewModel = TimelineViewModel()
@ObservedObject var authViewModel = AuthViewModel()
@ObservedObject var obs = observer()
var body: some View {
ZStack (alignment: .bottomTrailing) {
// Map(coordinateRegion: $locationViewModel.region, showsUserLocation: true)
// .accentColor(Color("accentColor"))
// .edgesIgnoringSafeArea(.all)
mapView(geopoints: self.obs.data["data"] as! [String : GeoPoint]) <--- /!\ the problem occurs here /!\
Button {
showNewPostView.toggle()
} label: {
Image(systemName: "plus")
.resizable()
.renderingMode(.template)
.frame(width: 30, height: 30)
.font(.system(size: 30, weight: .bold, design: .default))
.padding()
}
.background(Color("accentColor"))
.foregroundColor(Color("backgroundColor"))
.clipShape(Circle())
.padding()
.shadow(radius: 20)
.fullScreenCover(isPresented: $showNewPostView) {
uploadPostView()
}
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("home")
.background(Color("backgroundColor"))
}
}
struct mapTimelineView_Previews: PreviewProvider {
static var previews: some View {
mapTimelineView()
}
}
struct mapView: UIViewRepresentable {
@ObservedObject var authViewModel = AuthViewModel()
var geopoints : [String: GeoPoint]
func makeCoordinator() -> Coordinator {
return mapView.Coordinator(parent1: self)
}
let map = MKMapView()
let manager = CLLocationManager()
func makeUIView(context: Context) -> MKMapView {
manager.delegate = context.coordinator
manager.startUpdatingLocation()
map.showsUserLocation = true
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 48.856614, longitude: 2.3522219), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05))
map.region = region
return map
}
func updateUIView(_ uiView: MKMapView, context: Context) {
for i in geopoints {
let point = MKPointAnnotation()
point.coordinate = CLLocationCoordinate2D(latitude: i.value.latitude, longitude: i.value.longitude)
point.title = i.key
uiView.removeAnnotations(uiView.annotations)
uiView.addAnnotation(point)
}
}
class Coordinator: NSObject, CLLocationManagerDelegate {
@ObservedObject var authViewModel = AuthViewModel()
var parent: mapView
init(parent1: mapView) {
parent = parent1
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let uid = self.authViewModel.userSession?.uid else { return }
let last = locations.last
Firestore.firestore().collection("locations").document("coordinate").setData(["updates" : [uid : GeoPoint(latitude: (last?.coordinate.latitude)!, longitude: (last?.coordinate.longitude)!)]],merge: true) { (err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
print("success")
}
}
}
}
class observer : ObservableObject{
@Published var data = [String : Any]()
init() {
let db = Firestore.firestore()
db.collection("locations").document("coordinate").addSnapshotListener { (snap, err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
let updates = snap?.get("updates") as! [String : GeoPoint]
self.data["data"] = updates
}
}
}
It shows a map and the user location. But my problem is that my app crash because there is "nil" on this line :
mapView(geopoints: self.obs.data["data"] as! [String : GeoPoint])
I got this error message :
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
And, I don't understand this issue because I do have data in my database :

So, if anyone has a solution, I would like to know it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
