swift - 如何在闭包中调用函数

标签 swift block cllocation completionhandler

在模型的类Location中,我获取当前城市的名称:

var currentLatitude: Double!
var currentLongitude: Double!
var currentLocation: String!
var currentCity: String!

func getLocationName() {

    let geoCoder = CLGeocoder()
    let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)

    geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
        guard let addressDict = placemarks?[0].addressDictionary else {
            return
        }
        if let city = addressDict["City"] as? String {
            self.currentCity = city
            print(city)
        }
        if let zip = addressDict["ZIP"] as? String {
            print(zip)
        }
        if let country = addressDict["Country"] as? String {
            print(country)
        }

        self.nowUpdateUI()
    })
}

在 View Controller 中,我想更新 UI 并更新标签以显示当前城市。 然而, self.currentCity = city 发生在闭包内部。因此,如果我只是在 View Controller 中运行一个函数:

func updateUI() {
        cityLbl.text = Location.sharedInstance.currentCity
}
  • 我一无所获,因为闭包尚未完成运行。 建议我向 getLocationName() 添加一个完成处理程序,并在其中执行对将更新 UI 的 func 的调用。 然而,从所有关于闭包、完成处理程序的教程中,我不清楚如何实现这一点。 如何构造完成处理程序,将其作为参数传递给 getLocationName() 以及如何从 View Controller 调用 getLocationName

最佳答案

要处理这种情况,您有多种选择。

  1. 使用您的位置类创建委托(delegate)/协议(protocol)

    • 创建一个协议(protocol)并使用您的 ViewController 实现该协议(protocol)方法,并在您的 Location 类中声明其实例。然后在reverseGeocodeLocationcompletionHandler中调用这个委托(delegate)方法。查看 Apple 文档 Protocol了解更多详情。
  2. 您可以使用 Location 类的 getLocationName 方法创建 completionHandler

    • 使用 getLocationName 添加 completionHandler 并在 reverseGeocodeLocation 的 completionHandler 内调用该 completionHandler 像这样。

      func getLocationName(completionHandler: @escaping (_ success: Bool) -> Void) {
      
          let geoCoder = CLGeocoder()
          let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
      
          geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
              guard let addressDict = placemarks?[0].addressDictionary else {
                  completionHandler(false)
                  return
              }
              if let city = addressDict["City"] as? String {
                  self.currentCity = city
                  print(city)
              }
              if let zip = addressDict["ZIP"] as? String {
                  print(zip)
              }
              if let country = addressDict["Country"] as? String {
                  print(country)
              }
              completionHandler(true)
              //self.nowUpdateUI()
          })
      }
      

      现在,在调用此函数的 ViewController 中,调用完成 block 内的 updateUI 方法。

      Location.sharedInstance.getLocationName { (success) in
          if success {//If successfully got response
              self.updateUI()
          }
      }
      
  3. 您可以为 (NS)NotificationCenter 添加观察者。

    • 使用 (NS)NotificationCenter 注册观察者,然后在 reverseGeocodeLocationcompletionHandler 内发布通知。您可以通过此 StackOverflow Post 获得更多详细信息。 .

关于swift - 如何在闭包中调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42241177/

相关文章:

ios - UITabBarControllerDelegate 中的变量不更新

java - Eclipse 格式化。在为 block 打开大括号之前删除新行

Ruby 异步网络::HTTP?

iphone - CLLocation 和 double 的问题

ios - 在 IOS Objective-C 应用程序上向 Google map 添加标记图像

ios - 带有函数参数的 CoreData 谓词

ios - 使用推送通知快速打开特定 View

Swift 泛型和扩展需要锻炼

swift - 为了测试从 Firestore 提取的 Swift 应用程序,如何模拟 QuerySnapshot?

css - 将 CSS 转换应用于显示为 :block, 的元素会向页面添加大量滚动