Please note that for this app to be able show you your location on the map you need to enable it to ask for permission to track the user’s location, in the project’s targets’ info:
enable the iOS app to ask for permission to track the user’s location.
That being said, if you run this SwiftUI app and allow it to track your location, tap the MapUserLocationButton
and press the buttons at the bottom, you’ll see that the map lags:
import SwiftUI
import MapKit
import CoreLocation
struct ContentView: View {
let currentLocationManager = CurrentUserLocationManager()
let mapLocationsManager = MapLocationsManager()
@State private var mapCameraPosition: MapCameraPosition = .automatic
var body: some View {
Map(
position: $mapCameraPosition
)
.safeAreaInset(edge: .bottom) {
VStack {
if mapLocationsManager.shouldAllowSearches {
Button("First button") {
mapLocationsManager.shouldAllowSearches = false
}
}
Button("Second button") {
mapLocationsManager.shouldAllowSearches = true
}
}
.frame(maxWidth: .infinity)
.padding()
}
.mapControls {
MapUserLocationButton()
}
}
}
@Observable class MapLocationsManager {
var shouldAllowSearches = false
}
// MARK: - Location related code -
class CurrentUserLocationManager: NSObject {
var locationManager: CLLocationManager?
override init() {
super.init()
startIfNecessary()
}
func startIfNecessary() {
if locationManager == nil {
locationManager = .init()
locationManager?.delegate = self
} else {
print(">> (Self.self).(#function): method called redundantly: locationManager had already been initialized")
}
}
}; extension CurrentUserLocationManager: CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
checkLocationAuthorization()
}
}; extension CurrentUserLocationManager {
private func checkLocationAuthorization() {
guard let locationManager else { return }
switch locationManager.authorizationStatus {
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
print("Your location is restricted")
case .denied:
print("Go into setting to change it")
case .authorizedAlways, .authorizedWhenInUse, .authorized:
// locationManager.startUpdatingLocation()
break
@unknown default:
break
}
}
}
I’ve also tried in a UIKit app, with the same results:
import UIKit
import MapKit
import SwiftUI
import CoreLocation
class ViewController: UIViewController {
let currentLocationManager = CurrentUserLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
currentLocationManager.startIfNecessary()
let hostingController = UIHostingController(
rootView: MapView()
)
addChild(hostingController)
hostingController.view.frame = view.bounds
hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
}
}
extension ViewController { struct MapView: View {
let mapLocationsManager = MapLocationsManager()
@State private var mapCameraPosition: MapCameraPosition = .automatic
var body: some View {
Map(
position: $mapCameraPosition
)
.safeAreaInset(edge: .bottom) {
VStack {
if mapLocationsManager.shouldAllowSearches {
Button("First button") {
mapLocationsManager.shouldAllowSearches = false
}
}
Button("Second button") {
mapLocationsManager.shouldAllowSearches = true
}
}
.frame(maxWidth: .infinity)
.padding()
}
.mapControls {
MapUserLocationButton()
}
}
} }
extension ViewController { @Observable class MapLocationsManager {
var shouldAllowSearches = false
} }
class CurrentUserLocationManager: NSObject {
var locationManager: CLLocationManager?
func startIfNecessary() {
if locationManager == nil {
locationManager = .init()
locationManager?.delegate = self
} else {
print(">> (Self.self).(#function): method called redundantly: locationManager had already been initialized")
}
}
}; extension CurrentUserLocationManager: CLLocationManagerDelegate {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
checkLocationAuthorization()
}
}; extension CurrentUserLocationManager {
private func checkLocationAuthorization() {
guard let locationManager else { return }
switch locationManager.authorizationStatus {
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .restricted:
print("Your location is restricted")
case .denied:
print("Go into setting to change it")
case .authorizedAlways, .authorizedWhenInUse, .authorized:
// locationManager.startUpdatingLocation()
break
@unknown default:
break
}
}
}
If you don’t center the map in the user’s location, you might see an occasiona lag, but it seems to me that this only happens once.
How do I avoid these lags altogether?
Xcode 15.4
Filippo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.