Show user coordinates SwiftUI
All you have to do is make the showsUserLocation
var true.(Look at the docs)
func makeUIView(context: UIViewRepresentableContext<MapView>) -> MKMapView {
let map = MKMapView()
let coordinate = CLLocationCoordinate2D(latitude: 55.757485, longitude: 37.632179)
map.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 100, longitudinalMeters: 100)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
// new code...
map.showsUserLocation = true
map.delegate = context.coordinator
map.addAnnotation(annotation)
return map
}
As of iOS 14 you can use the native SwiftUI Map. This might be easier to work with than bridging to UIKit
SwiftUI mapkit set region to user's current location
Here's one possible solution to this:
final class LocationManager: NSObject, ObservableObject {
@Published var location: CLLocation?
@Published var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 38.898150, longitude: -77.034340),
span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
)
private var hasSetRegion = false
private let locationManager = CLLocationManager()
override init() {
super.init()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.distanceFilter = kCLDistanceFilterNone
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
self.location = location
if !hasSetRegion {
self.region = MKCoordinateRegion(center: location.coordinate,
span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
hasSetRegion = true
}
}
}
}
struct ShowMapView: View {
@ObservedObject private var locationManager = LocationManager()
var homeLocation : [AnnotationItem] {
guard let location = locationManager.location?.coordinate else {
return []
}
return [.init(name: "Home", coordinate: location)]
}
var body: some View {
Map(coordinateRegion: $locationManager.region, annotationItems: homeLocation) {
MapPin(coordinate: $0.coordinate)
}
.frame(height: 300)
}
}
In this solution, the region is published by the location manager. As soon as a location is received, the region is centered on that spot (in didUpdateLocations
). Then, a boolean flag is set saying the region has been centered initially. After that boolean is set, it no longer updates the region. This will let the user still drag/zoom, etc.
I also changed your code for putting down the pin a little bit. You were force-unwrapping location
, which is nil until the first location is set by the location manager, causing a crash. In my edit, it just returns an empty array of annotation items if there isn't a location yet.
Swiftui + Core Location: Map fails to center on user
That is exactly your problem. Location data will ALWAYS lag, just like any other retrieved data. What you need to consider is a mechanism to update your views when you get updates.
The best way to do that is to import Combine
in your LocationManager
class and use a PassthroughSubject
like this:
let objectWillChange = PassthroughSubject<Void, Never>()
@Published var region = MKCoordinateRegion() {
willSet { objectWillChange.send() }
}
That allows you to subscribe to your publisher in the map and get updates. You will find many tutorials regarding this.
Retrieve user current location using SwiftUI and MapKit
Create instance of CLLocationManager
:
var locManager = CLLocationManager()
locManager.requestWhenInUseAuthorization()
then get the details:
var currentLocation: CLLocation!
if( CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways){
currentLocation = locManager.location
}
then to get longitude or latitude:
let longitude = currentLocation.coordinate.longitude
let latitude = currentLocation.coordinate.latitude
If you'd like to perform it inside a swiftUI view script, create instance:
@ObservedObject var locationManager = LocationManager()
Get them separately:
var userLatitude: String {
return "\(locationManager.lastLocation?.coordinate.latitude ?? 0)"
var userLongitude: String {
return "\(locationManager.lastLocation?.coordinate.longitude ?? 0)"
Related Topics
How to Synchronize Coredata with Webservices in Swift
How to Switch to Swift 4.0 in Xcode 9.3
Swift Language Statically or Dynamically Dispatched
Change the Font of a Datepicker
Are Swift Constants Lazy by Default
Menu Items Disabled in MACos Menubar App
Swiftui Multiline Text Background Color
Firebase and Reading Nested Data Using Swift
JSONserialization.JSONobject Performance in Swift
Why Are Properties of an Immutable Object Mutable in Swift
Why 'Self.Self' Compiles and Run in Swift
Swift Ui: Center Text into Circle