我正在使用 Xcode 12。
我能够显示带有区域的地图,但带有硬编码值。
相反,我想根据用户当前位置设置地图区域。
我有一个 LocationManager 类,它获取用户的位置并发布它。
我有一个 ShowMapView SwiftUI 视图,它观察基于 LocationManager 类的对象以获取用户的位置。但是,我不知道如何使用 locationManager 对象中的数据来设置地图使用的区域。
这是 LocationManager 类,它获取用户的位置并发布它。
import Foundation
import MapKit
final class LocationManager: NSObject, ObservableObject {
@Published var location: CLLocation?
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里是 ShowMapView SwiftUI View,它需要获取发布的用户位置并设置地图使用的区域。如您所见,这些值目前是硬编码的。
import Combine
import MapKit
import SwiftUI
struct AnnotationItem: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
struct ShowMapView: View {
@ObservedObject private var locationManager = LocationManager()
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 38.898150, longitude: -77.034340),
span: MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5)
)
var body: some View {
Map(coordinateRegion: $region, annotationItems: [AnnotationItem(name: "Home", coordinate: CLLocationCoordinate2D(latitude: self.locationManager.location!.coordinate.latitude, longitude: self.locationManager.location!.coordinate.longitude))]) {
MapPin(coordinate: $0.coordinate)
}
.frame(height: 300)
}
}
Run Code Online (Sandbox Code Playgroud)
这是一种可能的解决方案:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
在此解决方案中,区域由位置管理器发布。一旦收到位置,该区域就会以该点为中心(在 中didUpdateLocations)。然后,设置一个布尔标志,表示该区域最初已居中。设置该布尔值后,它不再更新该区域。这将使用户仍然可以拖动/缩放等。
我还更改了您的代码以稍微放下引脚。您正在强制展开location,直到位置管理器设置第一个位置为止,该值为零,从而导致崩溃。在我的编辑中,如果还没有位置,它只会返回一个空的注释项数组。
| 归档时间: |
|
| 查看次数: |
3462 次 |
| 最近记录: |