在地图SwiftUI上显示用户位置

时间:2019-06-12 01:29:20

标签: swift mapkit swiftui

我正在尝试加载地图,并将初始位置显示在用户的位置上,并使用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)
    }
}

当我尝试打印该位置时,该位置为零。

8 个答案:

答案 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的其他有用功能的更多信息。