首页 > 解决方案 > ReverseGeocodeLocation 补全在 viewDidLoad() swift4.1 中的使用

问题描述

斯威夫特版本:4.1

您好,我比 swift 的初学者多一点。在“按用户位置订购应用程序”中工作。reversegeocodelocation function在用户发出命令之前,我控制用户“国家”和“城市”名称。并将这些值写入 firebase 实时数据库子项。

我的数据结构就像

 -TR
   -Ankara
       -userID
           -Order(consist of user lat, user long, user mail, userOrder)

我这样做是可以的,用户可以订购和取消他/她的订单。但我也想检查用户是否关闭手机并返回应用程序,应用程序应该检查数据库,如果当前用户有命令,uID它必须更改按钮标签,buttonToCancelState = true和我们吉祥物的图像。

这就是我获取用户coord订单和数据结构名称的“国家代码”和“城市”的方式。

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

    let location = locations [0]

    if let coord = manager.location?.coordinate {
        userLocation = coord

    }


    let geoCoder = CLGeocoder()
    geoCoder.reverseGeocodeLocation(location) {(placemark, error) in
        if error != nil {
            print("there is an error")
        } else {

        var placeMark: CLPlacemark?
        placeMark = placemark?[0]


        // City
        if let city = placeMark?.locality {
            self.userCity = city as String

        }

        // Country
        if let country = placeMark?.isoCountryCode {
            self.userCountry = country as String
            }
        }
    }
}

我在“订单按钮”中使用了这些“国家”和“城市”,例如示例;

            orderHasBeenCalled = true
            buttonLabelText.text = "CANCEL/EDIT"
            imgView.image = UIImage(named: "...")
            let orderRequestDictionary: [String:Any] = ["..."]
            databaseREF.child(userCountry).child(userCity).child(userID!).setValue(orderRequestDictionary)

它完美地工作用户可以发送订单,即使用户注销它也删除它,(整个代码不包括在内)

现在的问题是我想检查用户在 viewDidLoad()我正在使用的负载时是否有订单

if let userID = FirebaseAuth.Auth.auth().currentUser?.uid {
        databaseRef.child(userCountry).child(userCity).queryOrdered(byChild: userID!).observe(.childAdded, with: { (snapshot) in
            self.OrderHasBeenCalled = true
            self.buttonLabelText.text = "CANCEL/EDIT"
            self.imgView.image = UIImage(named: "...")
            databaseRef.child(self.userCountry).child(self.userCity).removeAllObservers()
        })
   }

现在的问题是我在互联网上读到的reversegeocode是异步的或类似的东西,当 viewDidLoad() 加载时它似乎还没有准备好,“检查是否有订单的代码”使应用程序崩溃,因为它找不到搜索名称的价值在孩子们。

Terminating app due to uncaught exception 'InvalidPathValidation', reason: '(child:) Must be a non-empty string and not contain '.' '#' '$' '[' or ']''

为了在 orderbutton 中使用 userCountry 和 userCity,我在 viewDidLoad() 之前定义了它们

var userCountry = String()
var userCity = String()

我尝试了很多方法,但并没有真正弄清楚如何在 viewdidload() 中完成反向地理编码。我也试过viewDidAppear()了,但它也给了 userCountry() 和 userCity() nil。

我希望我的问题清晰易懂。如果答案会以这种方式,将不胜感激。在互联网上做了很多研究,有些我尝试了,有些我不明白或不知道我该如何尝试。我希望闪耀的最后一个地方是堆栈溢出。到目前为止,感谢所有热情地回答我的问题的人。

标签: iosswiftreverse-geocodingcompletionhandler

解决方案


我会改变一点方法。使用异步函数后,您必须避免同步请求值。

有几种方法可以从异步函数进行嵌套调用,从你的代码中我得出这种方法,适应你的需要,它应该可以工作。

/////////attention the scope (must be above class declaration)
typealias CompletionGetAddress = (_ userCity : String?, _ userCountry: String?, _ success: Bool) -> Void
var userLocation = CLLocationCoordinate2D()
var locationManager = CLLocationManager()
//

class viewController: ... {
func viewDidLoad() {

    yourLocationManager.requestLocation()

    // you should implement some code to ensure your userLocation from your locationManager is not nil and a valid location

    if let userID = FirebaseAuth.Auth.auth().currentUser?.uid {
        if self.userCity != "" {
            databaseRef.child(userCountry).child(userCity).queryOrdered(byChild: userID!).observe(.childAdded, with: { (snapshot) in
                self.OrderHasBeenCalled = true
                self.buttonLabelText.text = "CANCEL/EDIT"
                self.imgView.image = UIImage(named: "...")
                databaseRef.child(self.userCountry).child(self.userCity).removeAllObservers()
            })
        } else {
            getAddress { (city, country, success) in
                if success {
                    self.userCity = city
                    self.userCountry = country
                    databaseRef.child(userCountry).child(userCity).queryOrdered(byChild: userID!).observe(.childAdded, with: { (snapshot) in
                        self.OrderHasBeenCalled = true
                        self.buttonLabelText.text = "CANCEL/EDIT"
                        self.imgView.image = UIImage(named: "...")
                        databaseRef.child(self.userCountry).child(self.userCity).removeAllObservers()
                    })
                }
            }           
        }
    }
} 
}


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

    let location = locations [0]

    if let coord = manager.location?.coordinate {
        userLocation = coord /// attention here 

    }
}


func getAddress(completion: @escaping CompletionGetAddress) {
    let geoCoder = CLGeocoder()
    geoCoder.reverseGeocodeLocation(userLocation) {(placemark, error) in
        if error != nil {
            print("there is an error")
            completion(nil, nil, false)
        } else {
            var city: String = ""
            var country: String = ""
            var placeMark: CLPlacemark?
            placeMark = placemark?[0]
            // City
            if let c = placeMark?.locality {
                city = c
            }
            // Country
            if let c = placeMark?.isoCountryCode {
                country = c
            }
            completion(city, country, true)
        }
    }
}   

推荐阅读