我正在尝试加载地图,并将初始位置显示在用户的位置上,并使用SwiftUI在地图上显示用户的位置。我不知道如何在SwiftUI中做到这一点。
我试图将'view.showsUserLocation = true'放在updateUIView函数中,但是它不起作用。
import SwiftUI
import MapKit
struct MapView : UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
view.showsUserLocation = true
let coordinate = CLLocationCoordinate2D(
latitude: 34.011286, longitude: -116.166868)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: view.userLocation.location?.coordinate ?? coordinate, span: span)
view.setRegion(region, animated: true)
}
}
当我尝试打印该位置时,该位置为零。
答案 0 :(得分:1)
这是我找到的设置CoreLocation和MapView的最干净的方法。首先,您必须创建一个UIViewRepresentable才能在SwiftUI中使用CoreLocation。
不要忘记在您的Info.plist文件中启用此隐私权并显示以下消息:
隐私-位置始终且使用时使用情况说明
隐私-使用时的位置用法说明
隐私-位置始终使用说明
import SwiftUI
import MapKit
// MARK: Struct that handle the map
struct MapView: UIViewRepresentable {
@Binding var locationManager: CLLocationManager
@Binding var showMapAlert: Bool
let map = MKMapView()
///Creating map view at startup
func makeUIView(context: Context) -> MKMapView {
locationManager.delegate = context.coordinator
return map
}
func updateUIView(_ view: MKMapView, context: Context) {
map.showsUserLocation = true
map.userTrackingMode = .follow
}
///Use class Coordinator method
func makeCoordinator() -> MapView.Coordinator {
return Coordinator(mapView: self)
}
//MARK: - Core Location manager delegate
class Coordinator: NSObject, CLLocationManagerDelegate {
var mapView: MapView
init(mapView: MapView) {
self.mapView = mapView
}
///Switch between user location status
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
break
case .denied:
mapView.showMapAlert.toggle()
return
case .notDetermined:
mapView.locationManager.requestWhenInUseAuthorization()
return
case .authorizedWhenInUse:
return
case .authorizedAlways:
mapView.locationManager.allowsBackgroundLocationUpdates = true
mapView.locationManager.pausesLocationUpdatesAutomatically = false
return
@unknown default:
break
}
mapView.locationManager.startUpdatingLocation()
}
}
}
}
这是我在SwiftUI视图中使用它的方式。如果Coordinator类开关中的权限被拒绝,则会触发警报:
import SwiftUI
import CoreLocation
// MARK: View that shows map to users
struct HomeView: View {
@State var locationManager = CLLocationManager()
@State var showMapAlert = false
var body: some View {
MapView(locationManager: $locationManager, showMapAlert: $showMapAlert)
.alert(isPresented: $showMapAlert) {
Alert(title: Text("Location access denied"),
message: Text("Your location is needed"),
primaryButton: .cancel(),
secondaryButton: .default(Text("Settings"),
action: { self.goToDeviceSettings() }))
}
}
}
extension HomeView {
///Path to device settings if location is disabled
func goToDeviceSettings() {
guard let url = URL.init(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
答案 1 :(得分:0)
在Privacy - Location When In Use Usage Description
中添加密钥Info.plist
和说明
然后尝试更新以下功能:
func updateUIView(_ view: MKMapView, context: Context) {
view.showsUserLocation = true
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
// self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
self.locationManager.startUpdatingLocation()
//Temporary fix: App crashes as it may execute before getting users current location
//Try to run on device without DispatchQueue
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
let locValue:CLLocationCoordinate2D = self.locationManager.location!.coordinate
print("CURRENT LOCATION = \(locValue.latitude) \(locValue.longitude)")
let coordinate = CLLocationCoordinate2D(
latitude: locValue.latitude, longitude: locValue.longitude)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
})
}
}
答案 2 :(得分:0)
尝试这个:
struct OriginMap : UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<OriginMap>) -> MKMapView{
MKMapView()
}
func updateUIView(_ mapView: MKMapView, context: Context) {
let locationManager = CLLocationManager()
mapView.showsUserLocation = true
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
let locValue:CLLocationCoordinate2D = locationManager.location!.coordinate
let coordinate = CLLocationCoordinate2D(
latitude: locValue.latitude, longitude: locValue.longitude)
Datas.currentLocation = coordinate
let span = MKCoordinateSpan(latitudeDelta: 0.002, longitudeDelta: 0.002)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapView.setRegion(region, animated: true)
})
}}
答案 3 :(得分:0)
以上代码会由于不当的权限请求而导致应用程序崩溃。使用下面的代码可获得更好的性能和按时许可。
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
view.showsUserLocation = true
let locationManager = CLLocationManager()
let status = CLLocationManager.authorizationStatus()
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
if status == .authorizedAlways || status == .authorizedWhenInUse {
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
let location: CLLocationCoordinate2D = locationManager.location!.coordinate
let span = MKCoordinateSpan(latitudeDelta: 0.009, longitudeDelta: 0.009)
let region = MKCoordinateRegion(center: location, span: span)
view.setRegion(region, animated: true)
}
}
}
答案 4 :(得分:0)
使用它可以找到用户所在的地区
Text(Locale.current.localizedString(forRegionCode: Locale.current.regionCode!) ?? "")
.font(.system(size: 30))
.fontWeight(.bold)
答案 5 :(得分:0)
import SwiftUI
import MapKit
struct ContentView: View {
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: -23.506403, longitude: -46.1509555),
span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
var body: some View {
Map(coordinateRegion: $region, showsUserLocation: true)
}
}
答案 6 :(得分:-1)
可用于 XCode 12 。
import SwiftUI
import MapKit
struct ContentView: View {
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.321127, longitude: -122.047790),
span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5))
var body: some View {
Map(coordinateRegion: $region)
}
}
答案 7 :(得分:-1)
这是SwiftUI2的代码
import MapKit
import SwiftUI
struct MapView: View {
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.4353, longitude: 35.23442), span: MKCoordinateSpan(latitudeDelta: 0.15, longitudeDelta: 0.15))
var body: some View {
Map(coordinateRegion: $region)
}
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapView()
}
}
您还可以选中此URL,以获取有关添加到SwiftUI2的其他有用功能的更多信息。