You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI MVVM架构下坐标距离计算问题及代码修正求助

Swift MVVM架构下距离计算的位置与方法修复

问题背景

在Swift MVVM项目中,需获取房屋数据并展示其与用户的距离,当前存在两个核心问题:

  1. 不确定距离计算函数的合理放置位置,以及如何正确连接负责网络请求的ViewModel和负责定位的LocationManager;
  2. 自定义的distanceInKM方法始终返回占位值35.5,无法计算并展示实际距离。

解决方案

一、距离计算函数的位置与类整合

距离计算属于位置相关的工具逻辑,放在LocationManager中是合理的,但需解决视图层重复创建LocationManager实例的问题(当前HouseListView重新初始化实例会导致状态不同步)。

正确实现方式:

  1. 在根视图ContentView中创建唯一的LocationManager实例,通过参数传递给子视图,确保整个视图层级共享同一实例;
  2. 视图层同时观察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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:05:25