关闭在Swift

时间:2018-10-19 20:17:30

标签: ios swift closures

作为对用户操作的响应,我想将CLLocation转换为地址字符串,并将其显示回给用户。

因此序列是 1.用户操作触发序列 2. ReverseGeocoder向Apple的服务器发出请求,并异步返回结果。 3.向用户显示结果。

如果我有一个专用的方法,并且在完成块中的显示部分如下所示,我就可以显示结果:

  func userWantsAddress {        
    displayAddressFrom(location: myLocation)
    }
     func displayAddressFrom(location: CLLocation)  {
            CLGeocoder().reverseGeocodeLocation(location) { (placemark, error) in
                if error != nil {
                    print("error")

                } else {

                    let place = placemark! as [CLPlacemark]
                    if place.count > 0 {
                        let place = placemark![0]
                        var addressString : String = ""
                        if place.subThoroughfare != nil {
                            addressString = addressString + place.subThoroughfare! + "\n"
                        }
                        if place.thoroughfare != nil {
                            addressString = addressString + place.thoroughfare! + " in "
                        }

                        if place.locality != nil {
                            addressString = addressString + place.locality!
                        }

                        if place.subAdministrativeArea != nil {
                            addressString = addressString + ", "+place.subAdministrativeArea!
                        }
    //THIS IS WHERE YOU DISPLAY
                        myLabel.text = "THE LOCATION IS \(addressString)"
                        print("the location is",addressString)

                    }
                }
            }

        }

但是,我想做的是简化代码,以便一旦获得结果,就将它们返回到调用方法的闭包中进行自定义,这样我就可以重用addressFromString方法(而不必重写每次我想将位置转换为地址时都使用它),但是我不知道语法。

我认为我需要给第一种方法一个完成块,以等待第二种方法的完成。并且第二次返回结果将导致闭包:类似

    func userWantsAddress(location: myLocation completion:@escaping (_ response:String)->()){

        displayAddressFrom(location: myLocation completion:completion) {

completion("HERE IS YOUR ADDRESS")
        }

但是,我似乎无法正确理解

对于如何执行此操作的任何建议将不胜感激。

1 个答案:

答案 0 :(得分:2)

您只需要在方法中添加完成处理程序,并在调用完成时返回第一个地标:

func displayAddressFrom(location: CLLocation, completion: @escaping (CLPlacemark?, Error?) -> ())  {
    CLGeocoder().reverseGeocodeLocation(location) { 
        completion($0?.first, $1) 
    }
}

let location = CLLocation(latitude: -22.963451, longitude: -43.198242)
displayAddressFrom(location: location) { placemark, error in
    guard let placemark = placemark, error == nil else { return }
    // Update your UI from the main thread
    DispatchQueue.main.async {
        //  UI update here
        print(placemark)
    }
}

  

Morro da Saudade,Morro da Saudade,Rua Casuarina,443,拉各斯,里约热内卢   Janeiro-RJ,22011-040,巴西@ <-22.96345100,-43.19824200> +/-   100.00m,区域CLCircularRegion(标识:'<-22.96345100,-43.19824200>半径141.83',   中心:<-22.96345100,-43.19824200>,半径:141.83m)


如果您需要地标中的邮件字符串,则可以获取其postalAddress并使用CNPostalAddressFormatter string(for :)方法从中创建字符串:

import Contacts
extension CNPostalAddress {
    var mailingAddress: String {
        return CNPostalAddressFormatter.string(from: self, style: .mailingAddress)
    }
}

DispatchQueue.main.async {
    //  UI update here
    print(placemark.postalAddress?.mailingAddress ?? "")   // "Rua Casuarina, 443\nLagoa\nRio de Janeiro RJ\n22011-040\nBrazil"
}

  

Rua Casuarina,443拉各斯里约热内卢RJ 22011-040巴西