无法在didUpdateLocations中比较Firebase的纬度/经度值

时间:2019-04-07 03:18:51

标签: ios swift firebase firebase-realtime-database cllocationmanager

我正在处理一个有关从Firebase提取数据并在代码中其他地方使用该数据的简单问题。下面,我有一个函数来检索位置的纬度和经度,并将它们存储在两个已定义并初始设置为0.0的变量locationLatlocationLong中。我在viewDidLoad中调用此函数。

然后在didUpdateLocations中访问保存纬度和经度的两个变量,以将用户的位置与从Firebase获取的值的纬度和经度进行比较。

我的问题:didUpdateLocations中的if条件不会一直有效,当它不起作用时,纬度和经度将显示0.0或nil,并且不会运行if语句。

我了解到observeSingleEvent本质上是异步的,但是我不确定如何在我的代码中正确使用Firebase数据,尤其是在didUpdateLocations委托函数中检索时。任何建议都很好。

以下是与此问题相关的两个功能。第一个是我的函数,该函数从Firebase检索纬度和经度。第二个函数是我的didUpdateLocations函数,发生错误。

func getLocationCoordinates() {
        let ref = Database.database().reference().child("map").child(self.titleString)
        ref.observeSingleEvent(of: .value) { (snapshot) in
                let nameSnapshots = snapshot.childSnapshot(forPath: "title")
                let val = nameSnapshots.value as! String
                if self.locationName.text == val {
                    let latitude = snapshot.childSnapshot(forPath: "latitude")
                    let longitude = snapshot.childSnapshot(forPath: "longitude")
                    let latValue = latitude.value as! CLLocationDegrees
                    let lonValue = longitude.value as! CLLocationDegrees
                    self.locationLat = latValue
                    self.locationLong = lonValue
                }
            }
        }

这是didUpdateLocations函数

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        manager.desiredAccuracy = kCLLocationAccuracyBest
        let userLocation :CLLocation = locations[0] as CLLocation
        let locationAddress: CLLocation = CLLocation(latitude: locationLat, longitude: locationLong)
        print("loc latitude = \(locationAddress.coordinate.latitude)")
        print("loc longitude = \(locationAddress.coordinate.longitude)")
        let distanceFrom : CLLocationDistance = userLocation.distance(from: locationAddress)
        if 300 >= distanceFrom {
            checkInOutlet.isEnabled = true
            print("we are here")
        } else {
            checkInOutlet.isEnabled = false
            print("not here yet")
        }
        locationManager.stopUpdatingLocation()
    }

1 个答案:

答案 0 :(得分:2)

由于您的getLocationCoordinatesdidUpdateLocationsasync个调用,因此您需要等到getLocationCoordinates从Firebase服务器给出结果并在didUpdateLocations方法中使用返回值

为此,您可以使用completion闭包。检查以下示例代码:

func getLocationCoordinates(completion: @escaping (_ lat: CLLocationDegrees, _ lon: CLLocationDegrees)->()) {

    let ref = Database.database().reference().child("map").child(self.titleString)
    ref.observeSingleEvent(of: .value) { (snapshot) in
        let nameSnapshots = snapshot.childSnapshot(forPath: "title")
        let val = nameSnapshots.value as! String
        if self.locationName.text == val {
            let latitude = snapshot.childSnapshot(forPath: "latitude")
            let longitude = snapshot.childSnapshot(forPath: "longitude")
            let latValue = latitude.value as! CLLocationDegrees
            let lonValue = longitude.value as! CLLocationDegrees
            self.locationLat = latValue
            self.locationLong = lonValue

            completion(latValue, lonValue) //this will return your data
        }
    }
}

我已使用getLocationCoordinates回调修改了您的completion,并且completion将在从Firebase服务器获取数据并从中返回latlon的值时调用打电话。

现在,您需要在didUpdateLocations方法中使用它,如下所示:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    manager.desiredAccuracy = kCLLocationAccuracyBest
    let userLocation :CLLocation = locations[0] as CLLocation

    //call your method like this
    getLocationCoordinates { (lat, lon) -> () in

        //use lat and lon which returned by above method
        let locationAddress: CLLocation = CLLocation(latitude: lat, longitude: lon)
        print("loc latitude = \(locationAddress.coordinate.latitude)")
        print("loc longitude = \(locationAddress.coordinate.longitude)")
        let distanceFrom : CLLocationDistance = userLocation.distance(from: locationAddress)
        if 300 >= distanceFrom {
            self.checkInOutlet.isEnabled = true
            print("we are here")
        } else {
            self.checkInOutlet.isEnabled = false
            print("not here yet")
        }
        self.locationManager.stopUpdatingLocation()
    }
}