SwiftUI。尝试使用 @Binding 在视图之间传递变量,但不断出现错误

问题描述 投票:0回答:1

我有这个函数,可以从纬度、经度数组中查找到用户位置的最近位置。

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”放入函数中,然后从该函数获取最接近的变量结果作为绘制折线的“目的地”。有什么想法吗?

arrays swiftui location
1个回答
0
投票

这应该可以解决问题。 我还对您的代码进行了一些改进,使其更清晰。我真的不知道你的代码应该做什么,所以让我知道它是否有效。

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()
}
© www.soinside.com 2019 - 2024. All rights reserved.