在我的项目中,我获取有关房屋/建筑物的数据,以及其他细节,我展示了它离用户有多远。我只是一个初学者,所以我会尽量明确。
我的问题是,我不知道将计算公里距离的函数放在哪里,以及如何在MVVM项目中正确调用它。请注意,我有一个ViewModel文件,其中包括负责网络的ViewModel类和负责跟踪用户位置的LocationManager类。纬度和经度来自API的ViewModel,我认为距离的计算应该用LocationManager进行。我不知道如何“连接”这两个类。
我的主要目标是:
distanceInKM方法是否正确。尽管它不抛出,但它仍然显示一个占位符值。作为最小可重复的项目,下面是代码:
ContentView:
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
@StateObject var locationManager = LocationManager()
var body: some View {
VStack {
HouseListView(housesVM: viewModel)
}
.onAppear {
viewModel.fetchHouses()
}
}
}HouseListView(在ContentView中调用的视图:
struct HouseListView: View {
@ObservedObject var housesVM: ViewModel
@StateObject var locationManager = LocationManager()
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .leading) {
ForEach(housesVM.info, id: \.id) { house in
GetHouseCellView(
distance: Double(locationManager.distanceInKM(latitude: house.latitude, longitude: house.longitude)) ?? 0.00, //Here's the place where function is called
bedrooms: house.bedrooms)
}
}
}
}
private func GetHouseCellView(distance: Double, bedrooms: Int) -> some View {
HStack(spacing: 20) {
Label("\(bedrooms)", image: "bed-2")
Label("\(distance) km", image: "pin") //Here the final distance should be displayed, i.e 36,4 km
}
}非常基本的ViewModel:
class ViewModel: ObservableObject {
@Published var info: [Houses] = []
func fetchHouses() {
//URL & URLRequest here
let dataTask = URLSession.shared.dataTask(with: request) { data, response, error in
let decoder = JSONDecoder()
do {
if let data = data {
let result = try decoder.decode([Houses].self, from: data)
DispatchQueue.main.async {
self.info = result
}
}
} catch {
print("whoopsie! There's an error: \(error.localizedDescription)")
}
}
dataTask.resume()
}
}
}和一个LocationManager:
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
@Published var locationStatus: CLAuthorizationStatus?
@Published var lastLocation: CLLocation?
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
var statusString: String {
guard let status = locationStatus else {
return "unknown"
}
switch status {
case .notDetermined: return "notDetermined"
case .authorizedWhenInUse: return "authorizedWhenInUse"
case .authorizedAlways: return "authorizedAlways"
case .restricted: return "restricted"
case .denied: return "denied"
default: return "unknown"
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
locationStatus = status
print(#function, statusString)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
lastLocation = location
print(#function, location)
}
func distanceInKM(latitude: Int, longitude: Int) -> Double { //Here's the method I made to calculate an actual distance
let houseCoordinates = CLLocation(latitude: CLLocationDegrees(latitude), longitude: CLLocationDegrees(longitude))
let userCoordinates = CLLocation(latitude: lastLocation?.coordinate.latitude ?? 50, longitude: lastLocation?.coordinate.longitude ?? 30)
let distance = userCoordinates.distance(from: houseCoordinates) / 1000 //.distance comes in meters so /1000 is to have a KM value
let s = String(format: "%.0f", distance)
return Double(s + "Km") ?? 35.5 // This value of 35.5 as placeholder is constantly displayed instead of the actual value
}
}这个功能逻辑是taken from this post
发布于 2022-09-16 12:08:04
简单类型错误:
Double(s + "Km")将始终返回0作为s+ "Km“不是有效的双。
只需返回:
Double(distance)如果要返回字符串,请更改方法的类型并返回
s + "km"编辑:如果要以km : in GetHouseCellView显示距离,请将距离标签更改为:
Label(String(format: "%.2f km", distance), image: "pin")使用它时,最好将距离设置为双倍格式。
https://stackoverflow.com/questions/73735692
复制相似问题