我有这个函数,可以从纬度、经度数组中查找到用户位置的最近位置。
func getClosest(){
let LRK = CLLocation(latitude: 37.944804, longitude: -122.509066)
let SAU = CLLocation(latitude: 37.856315, longitude: -122.478723)
let SFO = CLLocation(latitude: 37.795346, longitude: -122.392711)
//let TEST = CLLocation(latitude: 37.947112, longitude: -122.490452)
let coordinates = [LRK, SAU, SFO]
let userLocation = CLLocation(latitude: 37.944804, longitude: -122.509066)
@State var closest = coordinates.min(by:
{ $0.distance(from: userLocation) < $1.distance(from: userLocation) })
print("Closest from Function", (closest))
}
在主 swift 文件中,我尝试使用该位置作为目的地,然后在两者之间绘制一条折线。
import SwiftUI
import MapKit
@Observable
class NewLocationManager {
var location: CLLocation? = nil
private let locationManager = CLLocationManager()
func requestUserAuthorization() async throws {
locationManager.requestWhenInUseAuthorization()
}
func startCurrentLocationUpdates() async throws {
for try await locationUpdate in CLLocationUpdate.liveUpdates() {
// adjust the logic/parameters as you require
let oldLocation = self.location == nil ? CLLocation() : self.location!
guard let newLocation = locationUpdate.location else { return }
if !oldLocation.isClose(to: newLocation, withinDistance: 50.0) {
self.location = newLocation
}
}
}
}
func getClosest(){
let LRK = CLLocation(latitude: 37.944804, longitude: -122.509066)
let SAU = CLLocation(latitude: 37.856315, longitude: -122.478723)
let SFO = CLLocation(latitude: 37.795346, longitude: -122.392711)
//let TEST = CLLocation(latitude: 37.947112, longitude: -122.490452)
let coordinates = [LRK, SAU, SFO]
let userLocation = CLLocation(latitude: 37.944804, longitude: -122.509066)
@State var closest = coordinates.min(by:
{ $0.distance(from: userLocation) < $1.distance(from: userLocation) })
print("Closest from Function", (closest))
}
struct ContentView: View {
@State var newlocationManager = NewLocationManager()
@State private var selectedResult: MKMapItem?
@State private var route: MKRoute?
private let destination = CLLocationCoordinate2D(latitude: 38.944804, longitude: -122.509066)
@State private var myLocation = CLLocationCoordinate2D(latitude: 35.67, longitude: 139.763) // <--- here @State
var body: some View {
Map(selection: $selectedResult) {
UserAnnotation()
// Adding the marker for the starting point
Marker("Start", coordinate: destination)
// Show the route if it is available
if let route {
MapPolyline(route)
.stroke(.blue, lineWidth: 5)
}
}
.onChange(of: newlocationManager.location) { // <--- here
if let coord = newlocationManager.location?.coordinate {
myLocation = coord
getDirections2()
}
}
.task {
try? await newlocationManager.requestUserAuthorization()
try? await newlocationManager.startCurrentLocationUpdates()
// remember that nothing will run here until the for try await loop finishes
}
.onAppear {
CLLocationManager().requestWhenInUseAuthorization()
selectedResult = MKMapItem(placemark: MKPlacemark(coordinate: myLocation))
}
}
// --- here
func getDirections2() {
route = nil
// Create and configure the request
let request = MKDirections.Request()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: destination))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: myLocation))
// Get the directions based on the request
Task {
let directions = MKDirections(request: request)
let response = try? await directions.calculate()
route = response?.routes.first
}
}
}
extension CLLocation {
func isClose(to otherLocation: CLLocation, withinDistance distance: CLLocationDistance) -> Bool {
return self.distance(from: otherLocation) <= distance
}
}
#Preview {
ContentView()
}
我不能做的是将“userLocation”放入函数中,然后从该函数获取最接近的变量结果作为绘制折线的“目的地”。有什么想法吗?
这应该可以解决问题。 我还对您的代码进行了一些改进,使其更清晰。我真的不知道你的代码应该做什么,所以让我知道它是否有效。
import SwiftUI
import MapKit
import CoreLocation
// Define the function to get the closest location
func getClosest(userLocation: CLLocation, locations: [CLLocation]) -> CLLocation? {
return locations.min(by: { $0.distance(from: userLocation) < $1.distance(from: userLocation) })
}
// Observable Location Manager class
class NewLocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
@Published var location: CLLocation? = nil
private let locationManager = CLLocationManager()
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let newLocation = locations.last else { return }
self.location = newLocation
}
}
// SwiftUI View
struct ContentView: View {
@StateObject var newLocationManager = NewLocationManager()
@State private var selectedResult: MKMapItem?
@State private var route: MKRoute?
@State private var destination: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 37.944804, longitude: -122.509066) // Default value
let locations = [
CLLocation(latitude: 37.944804, longitude: -122.509066), // LRK
CLLocation(latitude: 37.856315, longitude: -122.478723), // SAU
CLLocation(latitude: 37.795346, longitude: -122.392711) // SFO
]
var body: some View {
Map {
if let userLocation = newLocationManager.location {
Marker("Start", coordinate: destination)
Marker("User", coordinate: userLocation.coordinate)
if let route = route {
MapPolyline(route)
.stroke(.blue, lineWidth: 5)
}
}
}
.onChange(of: newLocationManager.location) {
if let userLocation = newLocationManager.location {
if let closestLocation = getClosest(userLocation: userLocation, locations: locations) {
destination = closestLocation.coordinate
getDirections()
}
}
}
}
func getDirections() {
guard let userLocation = newLocationManager.location else { return }
let request = MKDirections.Request()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: userLocation.coordinate))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: destination))
Task {
let directions = MKDirections(request: request)
do {
let response = try await directions.calculate()
route = response.routes.first
} catch {
print("Error getting directions: \(error)")
}
}
}
}
extension CLLocation {
func isClose(to otherLocation: CLLocation, withinDistance distance: CLLocationDistance) -> Bool {
return self.distance(from: otherLocation) <= distance
}
}
#Preview {
ContentView()
}