Reputation: 77
I want to allow users to zoom in/out and move freely around the map while the app is tracking and displaying their current location. Later i will try to add a button that you can press and it will move you back to the center of user location. I think the problem is that in my LocationManager file i am creating new region everytime i get a new location coordinates. But i do not know any other ways of tracking user location and displaying it.
LocationManager:
import Foundation
import CoreLocation
import MapKit
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate{
let locationManager = CLLocationManager()
@Published var location: CLLocationCoordinate2D?
@Published var region = MKCoordinateRegion()
override init(){
super.init()
locationManager.delegate = self
}
func startTracking() {
locationManager.requestAlwaysAuthorization()
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = kCLDistanceFilterNone
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
}
func stopTracking() {
print("stop test")
locationManager.stopUpdatingLocation()
locationManager.allowsBackgroundLocationUpdates = false
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let tempLocation = locations.last?.coordinate
print(tempLocation)
let center = CLLocationCoordinate2D(latitude: tempLocation?.latitude ?? 0.0, longitude: tempLocation?.longitude ?? 0.0)
let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
let tempRegion = MKCoordinateRegion(center: center, span: span)
DispatchQueue.main.async {
self.location = tempLocation
self.region = tempRegion
}
}
}
ContentView:
import SwiftUI
import MapKit
struct ContentView: View {
@State var isButtonPressed: Bool = false
@StateObject var locationManager = LocationManager()
var body: some View {
VStack{
Button("START"){
isButtonPressed = true
locationManager.startTracking()
}
Button("STOP"){
isButtonPressed = false
locationManager.stopTracking()
}
mapView(isButtonPressed: isButtonPressed, manager: locationManager)
}
}
}
struct mapView: View{
var isButtonPressed: Bool
@ObservedObject var manager: LocationManager
@State var defaultRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 0, longitude: 0), latitudinalMeters: 1000, longitudinalMeters: 1000)
var body: some View{
if isButtonPressed == true{
if let location = manager.location {
Map(coordinateRegion: $manager.region, interactionModes: .all, showsUserLocation: true, userTrackingMode:nil)
} else{
Map(coordinateRegion: $defaultRegion)
}
}
else
{
Map(coordinateRegion: $defaultRegion)
}
}
}
Thanks!
Upvotes: 0
Views: 746
Reputation: 131481
Creating a series of regions is the wrong way to monitor the user's location.
It's been quite a while since I've written a mapping app, but here's the general idea of what you should do:
Create an instance of the location manager.
Set yourself as the location manager's delegate.
Ask the user for permission to get location updates while your app is running (if you don't have permission already.)
Call startUpdatingLocation()
to request location updates
Respond to calls to the location manager delegate's locationManager(_:didUpdateLocations:)
method as needed. (If you set up the map to show the user's location you won't have to do anything special - the blue dot will update automatically.)
Upvotes: 0