【问题标题】:Get user location only working from second time on仅从第二次开始获取用户位置
【发布时间】:2019-01-09 11:36:30
【问题描述】:

首先:抱歉标题不好。我不知道如何更好地描述我的问题。

我的 Xcode 项目中有这段代码:

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()
    var currentLocation = "PLACEHOLDER"

    override func viewDidLoad() {
        self.locationManager.requestWhenInUseAuthorization()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        super.viewDidLoad()
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
        currentLocation = String(locValue.latitude)
    }
    @IBAction func sendLocation() {
        locationManager.startUpdatingLocation()
        print(currentLocation)
        locationManager.stopUpdatingLocation()
    }
}

这会在单击 UIButton 时打印用户位置。

这是有效的。但是由于某种原因,在重新启动应用程序后第一次按下 UIButton 时,它会打印PLACEHOLDER 而不是位置。

意思是:当我启动应用程序并单击 UIButton 三次时,我在控制台中得到了这个:

PLACEHOLDER
56.153666216328625
56.153666216328625

而不是这个:

56.153666216328625
56.153666216328625
56.153666216328625

我也尝试存储为UserDefaults 而不是var,但这会导致同样的问题。

我做错了什么?

【问题讨论】:

    标签: ios swift location cllocationmanager


    【解决方案1】:

    问题是位置更新是异步接收的,因此您在新的位置更新会触发委托调用 locationManager(_:, didUpdateLocations) 之前打印 currentLocation 的值,因此您的 currentLocation 变量会在打印之前打印出来更新。您需要在委托方法中打印值以显示更新后的值。

    顺便说一句,如果您想接收单个位置更新,则不应在彼此之后使用 startUpdatingLocationstopUpdatingLocation,尤其是因为您可能实际上在单个更新发生之前由于异步性而停止更新。您应该使用requestLocation 接收一次性位置更新。此外,您应该在委托调用中使用locations 变量,而不是manager.location

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let coordinate = locations.last?.coordinate else { return }
        currentLocation = String(coordinate.latitude)
        print(currentLocation)
    }
    
    @IBAction func sendLocation() {
        locationManager.requestLocation()
    }
    

    【讨论】:

    • 我已经尝试过locationManager.requestLocation() 而不是开始和停止,但这会使我的应用程序崩溃。知道为什么吗?我再次尝试使用您的代码,但它仍然与 locationManager.requestLocation() 崩溃。
    • 我需要通过 IBAction 致电 print(currentLocation)。有没有办法returncurrentLocation
    • @David 您还应该确保触发IBAction 的按钮在获得位置使用授权之前被禁用,可能由于在获得用户授权之前请求位置而导致崩溃。不,您不能返回currentLocation,因为委托方法是异步调用的。但是,由于委托方法只能在IBAction被触发后调用,所以实际上不需要从IBAction打印,在委托方法中打印也可以达到同样的效果
    • 授权不是问题。这是肯定的。
    • @David 那么你应该用崩溃原因编辑你的问题,否则我没有想法
    【解决方案2】:

    位置更新是异步发送给您的,因此您无法在调用 startUpdatingLocation() 后立即打印 currentLocation。

    只需将打印内容放在委托中

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return }
        currentLocation = String(locValue.latitude)
        print(currentLocation) // print only after updating the location
    }
    

    它应该可以工作

    【讨论】:

      猜你喜欢
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多