SwiftUI MVVM架构下坐标距离计算问题及代码修正求助
Swift MVVM架构下距离计算的位置与方法修复
问题背景
在Swift MVVM项目中,需获取房屋数据并展示其与用户的距离,当前存在两个核心问题:
- 不确定距离计算函数的合理放置位置,以及如何正确连接负责网络请求的
ViewModel和负责定位的LocationManager; - 自定义的
distanceInKM方法始终返回占位值35.5,无法计算并展示实际距离。
解决方案
一、距离计算函数的位置与类整合
距离计算属于位置相关的工具逻辑,放在LocationManager中是合理的,但需解决视图层重复创建LocationManager实例的问题(当前HouseListView重新初始化实例会导致状态不同步)。
正确实现方式:
- 在根视图
ContentView中创建唯一的LocationManager实例,通过参数传递给子视图,确保整个视图层级共享同一实例; - 视图层同时观察
ViewModel的房屋数据和LocationManager的位置数据,当两者都就绪时自动触发距离计算。
修改后的代码示例:
// ContentView struct ContentView: View { @ObservedObject var viewModel = ViewModel() @StateObject var locationManager = LocationManager() // 全局唯一的定位实例 var body: some View { VStack { // 将定位实例传递给子视图 HouseListView(housesVM: viewModel, locationManager: locationManager) } .onAppear { viewModel.fetchHouses() } } } // HouseListView struct HouseListView: View { @ObservedObject var housesVM: ViewModel @ObservedObject var locationManager: LocationManager // 接收父视图传递的实例,不再重复创建 var body: some View { ScrollView(.vertical, showsIndicators: false) { VStack(alignment: .leading) { ForEach(housesVM.info, id: \.id) { house in GetHouseCellView( distance: locationManager.distanceInKM(latitude: house.latitude, longitude: house.longitude), bedrooms: house.bedrooms) } } } } private func GetHouseCellView(distance: Double, bedrooms: Int) -> some View { HStack(spacing: 20) { Label("\(bedrooms)", image: "bed-2") // 在视图层处理距离的格式化展示 Label(String(format: "%.1f km", distance), image: "pin") } } }
二、修复distanceInKM方法的问题
当前方法的核心错误是字符串转换逻辑错误:将格式化后的距离字符串拼接"Km"后再转Double,必然转换失败,因此返回默认值35.5。
修改后的distanceInKM方法:
func distanceInKM(latitude: Int, longitude: Int) -> Double { // 先判断用户位置是否已获取,未获取则返回默认值 guard let userLocation = lastLocation else { return 0.0 } // 构造房屋位置坐标 let houseCoordinates = CLLocation(latitude: CLLocationDegrees(latitude), longitude: CLLocationDegrees(longitude)) // 计算距离(单位:米)并转换为千米 let distanceKM = userLocation.distance(from: houseCoordinates) / 1000.0 // 保留一位小数(可选,也可直接返回原始值,在视图层格式化) return round(distanceKM * 10) / 10 }
额外注意点:
- 建议API返回
Double类型的经纬度,当前Int类型精度不足,会影响计算准确性; - 需处理定位授权失败的情况,可在视图中根据
locationManager.locationStatus展示提示信息; - 距离计算只负责返回数值,格式化展示逻辑放在视图层,职责更清晰。
内容的提问来源于stack exchange,提问作者Ozzzie
相关产品推荐
相关产品推荐

