CLLocationManager 是异步的。对此有疑问

CLLocationManager is asynchronous. Having problems with this

我做的事情很简单

class HomeDatasourceController: UICollectionViewController, CLLocationManagerDelegate{
let locationManager:CLLocationManager = CLLocationManager()

//CurrentLocation is my variable that isn't changing on time
var currentLocation = CLLocation(latitude: 5.0, longitude: 5.0)

override func viewDidLoad() {
    super.viewDidLoad()


    locationManager.delegate = self
    locationManager.requestAlwaysAuthorization()
    self.locationManager.startUpdatingLocation()


    fetchHomeFeed()
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    for currentLocationTemp in locations {
        self.currentLocation = currentLocationTemp
        print("This is latitude: \(currentLocation.coordinate.latitude) , and this is longitude: \(currentLocation.coordinate.longitude)")
    }
}
fetchHomeFeed(){
    print("Hello: ", self.currentLocation)
}

调用 fetchHomeFeed 时,它只打印出我设置的虚拟位置(5.0 纬度和经度),而不是我的实际位置。 我知道这是异步的,但我不确定如何在第一次至少接到一次电话,这样我就可以正确地打印出我的位置(第一次)。

我还需要它在这之后继续更新,因为我想实时更新用户的位置。

我试过在 func locationManager 中使用 fetchHomeFeed(),但这会多次打印出 ("Hello: ", self.currentLocation),我只希望 fetchHomeFeed() 只被调用一次(具有适当的位置),然后连续调用该位置,因为我将有另一种方法使用它。

我不确定如何实现它。

来自documentation for didUpdateLocations

locations

An array of CLLocation objects containing the location data. This array always contains at least one object representing the current location. If updates were deferred or if multiple locations arrived before they could be delivered, the array may contain additional entries. The objects in the array are organized in the order in which they occurred. Therefore, the most recent location update is at the end of the array.

因此您无需遍历位置数组,只需使用 locations.last 除非您的应用程序需要担心延迟位置更新。

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let location = locations.last {
        currentLocation = location
    }
}

如果您希望 fetchHomeFeed 仅在一次调用时有多个选项,但最简单的是在调用它之前检查并在第一次调用时更改它的布尔标志。

从 viewDidLoad 中移除 fetchHomeFeed。这是不对的。

在您的 locationManager 函数中执行此操作。这将保证您有一个有效的位置。获得有效位置后,您将停止位置管理器,并在需要时重新启动。如果您想持续监控位置,那么您需要重新考虑解决方案,但这会给您一个想法。

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

        guard let location = locations.last else {
               return
        }

        if location.horizontalAccuracy > 0 {
             locationManager.stopUpdatingLocation()
             locationManager.delegate = nil
             fetchHomeFeed()
        }
    }