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

SwiftUI中CLLocationDistance返回异常巨大值问题求助

高尔夫APP中CLLocation计算距离异常巨大的问题修复

问题描述

开发高尔夫APP时遇到以下问题:使用CLLocation计算两点距离,控制台打印的坐标正确且两点位置极近,但返回的CLLocationDistance值却异常巨大(如9582674.806)。

APP逻辑:在ClubDetailView中,点击「Swing Location」按钮获取用户位置并设为shotCoord,按钮切换为「Ball Location」;再次点击按钮获取位置设为ballCoord,随后计算两者距离。使用iPad的Swift Playgrounds开发,获取的是实际设备位置。

原因分析

  1. 核心问题:点击「Swing Location」按钮时,仅调用了getShotLocation()获取位置,但没有将获取到的位置赋值给绑定的shotCoord变量。计算距离时使用的shotCoord是其初始值(通常是经纬度为0,0的位置,位于大西洋中部),和实际的ballCoord计算自然会得到超大距离。
  2. 次要问题:LocationManagerModel的requestAllowOnceLocationPermission方法中,调用requestLocation后立刻执行stopUpdatingLocation,可能导致位置还未完成更新就被停止,拿到的lastLocation可能是旧值或初始值。

修复方案(尽量少修改代码)

1. 修复shotCoord赋值问题

修改ClubDetailView中「Swing Location」按钮的action代码,将获取到的位置赋值给绑定的shotCoord:

if self.waiting == false{
    Button(action: {
       let shotCoords = getShotLocation()
        print("shotCoords = \(shotCoords)")
        // 新增:将获取到的位置赋值给绑定的shotCoord
        self.shotCoord = shotCoords
        self.waiting = true
    }, label: {
        Text("Swing Location")
            .foregroundColor(.white)
            .font(.system(.title, design: .rounded, weight: .bold))
            .frame(maxWidth: .infinity)
    })
    .buttonStyle(.borderedProminent)
}

2. 修复位置更新被提前停止的问题

修改LocationManagerModel中的requestAllowOnceLocationPermission方法,移除立刻停止更新的代码(requestLocation本身就是单次位置请求,无需手动停止):

func requestAllowOnceLocationPermission() {
    locationManager.requestLocation()
    // 移除这行代码:locationManager.stopUpdatingLocation()
}

3. 可选:添加位置非空校验(避免强制解包崩溃)

在getShotLocation和getBallLocation方法中添加非空校验,避免lastLocation为nil时崩溃:

func getShotLocation() -> CLLocation {
    locationManager.requestAllowOnceLocationPermission()
    // 简单等待位置更新(实际可结合异步回调优化)
    while locationManager.lastLocation == nil {
        RunLoop.current.run(until: Date().addingTimeInterval(0.1))
    }
    return locationManager.lastLocation!
}

func getBallLocation() -> CLLocation {
    locationManager.requestAllowOnceLocationPermission()
    while locationManager.lastLocation == nil {
        RunLoop.current.run(until: Date().addingTimeInterval(0.1))
    }
    return locationManager.lastLocation!
}

验证修改

修改后,点击「Swing Location」会将实际获取的位置赋值给shotCoord,再次点击「Ball Location」时,用两个实际获取的近距位置计算距离,就能得到正常的数值(单位是米,可自行转换为码:1码≈0.9144米)。

内容的提问来源于stack exchange,提问作者jhbetts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:15:58