I’m using MapKit in SwiftUI to display a map with the current location of the user. I have this code so far, but the problem is that I have to manually specify the region.
So my question is, How can I make the map always center around the current location of the user?
I’m not that experienced yet, so I hope you will have some patience with me
struct ContentView: View {
var body: some View {
Home()
}
}
struct Home: View{
@State var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 37.785834, longitude: -122.406417), latitudinalMeters: 1, longitudinalMeters: 1)
@State var tracking : MapUserTrackingMode = .follow
@State var manager = CLLocationManager()
@StateObject var managerDelegate = locationDelegate()
var body: some View {
VStack{
// Map(coordinateRegion: $region, interactionModes: .all, showsUserLocation: true, userTrackingMode: $tracking)
Map(coordinateRegion: $region, interactionModes: .all, showsUserLocation: true, userTrackingMode: $tracking, annotationItems: managerDelegate.pins) { pin in
MapPin(coordinate: pin.location.coordinate, tint: .red)
}.edgesIgnoringSafeArea(.all)
}.onAppear{
manager.delegate = managerDelegate
}
}
}
class locationDelegate: NSObject,ObservableObject,CLLocationManagerDelegate{
@Published var pins : [Pin] = []
// Checking authorization status...
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse{
print("Authorized")
manager.startUpdatingLocation()
} else {
print("not authorized")
manager.requestWhenInUseAuthorization()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
pins.append(Pin(location:locations.last!))
}
}
// Map pins for update
struct Pin : Identifiable {
var id = UUID().uuidString
var location : CLLocation
}
Thanks for the reply, I managed to update my code so the map is now always centered around the current location of the user. But I’m not sure my code is optimal, would appreciate it if you could take a quick look at it.
A problem I’m having with the new code is that when the user is moving, meaning if I set the simulator to simulate someone running or driving a car, I’m not able to zoom in or out or move the map at all. It keeps readjusting itself. Any ideas?
import SwiftUI
import MapKit
import CoreLocation
struct ContentView: View {
var body: some View {
Home()
}
}
struct Home: View{
@State var tracking : MapUserTrackingMode = .follow
@State var manager = CLLocationManager()
@StateObject var managerDelegate = locationDelegate()
var body: some View {
VStack{
Map(coordinateRegion: $managerDelegate.region, interactionModes: .all, showsUserLocation: true, userTrackingMode: $tracking, annotationItems: managerDelegate.pins) { pin in
MapPin(coordinate: pin.location.coordinate, tint: .red)
}.edgesIgnoringSafeArea(.all)
}.onAppear{
manager.delegate = managerDelegate
}
}
}
class locationDelegate: NSObject,ObservableObject,CLLocationManagerDelegate{
@Published var pins : [Pin] = []
// From here and down is new
@Published var location: CLLocation?
@State var hasSetRegion = false
@Published var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 38.898150, longitude: -77.034340),
span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1)
)
// Checking authorization status...
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse{
print("Authorized")
manager.startUpdatingLocation()
} else {
print("not authorized")
manager.requestWhenInUseAuthorization()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// pins.append(Pin(location:locations.last!))
// From here and down is new
if let location = locations.last {
self.location = location
if hasSetRegion == false{
region = MKCoordinateRegion(center: location.coordinate, span: MKCoordinateSpan(latitudeDelta: 0.001, longitudeDelta: 0.001))
hasSetRegion = true
}
}
}
}
// Map pins for update
struct Pin : Identifiable {
var id = UUID().uuidString
var location : CLLocation
}