【问题标题】:Swift CLGeocoder to get TimeZoneSwift CLGeocoder 获取 TimeZone
【发布时间】:2021-11-28 15:32:11
【问题描述】:

恐怕我的完成处理程序都搞砸了。我想要做的是使用纬度和经度来获得时区。我希望整个函数返回 TimeZone 类型的值。以下代码有效,因为我可以获得正确的 timeZone 但它在返回阶段崩溃了。

func getTimeZone(location: CLLocationCoordinate2D, completion: () -> TimeZone) -> TimeZone {
    
    var timeZone = TimeZone(identifier: "timeZone")
    var placemark: CLPlacemark?
    let cllLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
    let geocoder = CLGeocoder()
    
    geocoder.reverseGeocodeLocation(cllLocation) { placemarks, error in
        
        if let error = error {
            print(error.localizedDescription)
        } else {
            
            if let placemarks = placemarks {
                placemark = placemarks.first
            }
        }
        DispatchQueue.main.async {
            
            if let optTime = placemark?.timeZone {
                timeZone = optTime
            }

            return completion()
        }
    }
}

【问题讨论】:

    标签: swift timezone completionhandler clgeocoder clplacemark


    【解决方案1】:

    我认为完成实现存在问题。试着把它改成这样:

    func getTimeZone(location: CLLocationCoordinate2D, completion: @escaping ((TimeZone) -> Void)) {
        let cllLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
        let geocoder = CLGeocoder()
    
        geocoder.reverseGeocodeLocation(cllLocation) { placemarks, error in
    
            if let error = error {
                print(error.localizedDescription)
    
            } else {
                if let placemarks = placemarks {
                    if let optTime = placemarks.first!.timeZone {
                        completion(optTime)
                    }
                }
            }
        }
    }
    

    然后你可以这样调用函数:

    getTimeZone(location: CLLocationCoordinate2D(latitude: CLLocationDegrees(9.62), longitude: CLLocationDegrees(84.62))) { timeZone in
        print("Time zone: \(timeZone)")
    }
    

    【讨论】:

    • +1 表示正确答案,但为什么要花时间为已经有 2 个正确答案的问题写答案呢? (我认为 Sandeep 和我同时写下了我们的答案。)
    • @DuncanC 谢谢 :) 直到我添加了回复,我才意识到这一点。我认为我们几乎同时包含了这些响应。
    【解决方案2】:

    当你有异步reverseGeocodeLocation参与getTimeZone时,你为什么要尝试返回一个值

    func getTimeZone(location: CLLocationCoordinate2D, completion: @escaping (TimeZone) -> ()) {
            var placemark: CLPlacemark?
            let cllLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
            let geocoder = CLGeocoder()
    
            geocoder.reverseGeocodeLocation(cllLocation) { placemarks, error in
    
                if let error = error {
                    print(error.localizedDescription)
                } else {
    
                    if let placemarks = placemarks {
                        placemark = placemarks.first
                    }
                }
                DispatchQueue.main.async {
    
                    if let optTime = placemark?.timeZone {
                        completion(optTime)
                    }
                }
            }
        }
    

    终于把它当做

            getTimeZone(location: your_location_coordinates_here) {[weak self] timeZone in
                debugPrint(timeZone)
            }
    

    【讨论】:

      【解决方案3】:

      你说得差不多了。摆脱返回值。您不能从这样的异步函数返回函数结果。

      相反,调用者传入一个完成处理程序,该处理程序在返回结果时执行:

      func getTimeZone(location: CLLocationCoordinate2D, completion:  @escaping (TimeZone) -> ()) {
          
          var timeZone = TimeZone(identifier: "timeZone")
          var placemark: CLPlacemark?
          let cllLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
          let geocoder = CLGeocoder()
          
          geocoder.reverseGeocodeLocation(cllLocation) { placemarks, error in
              
              if let error = error {
                  print(error.localizedDescription)
              } else {
                  
                  if let placemarks = placemarks {
                      placemark = placemarks.first
                  }
              }
              DispatchQueue.main.async {
                  
                  if let optTime = placemark?.timeZone {
                      timeZone = optTime
                  }
                  completion(timeZone)
              }
          }
      }
      

      然后,使用它:

      getTimeZone(location: someLocation) { timeZone in
         // This code will execute once the time zone is calculated.
         print("The time zone for that location is \(timeZone.description)")
      }
      

      【讨论】:

      • completion: () -> TimeZone 不应该是completion: (TimeZone) -> ()??
      • (对于一个完整的实现,你应该在闭包的参数中添加一个可选错误,并在请求失败时返回。我把它留给你。)
      • @SandeepBhandari 确实应该。我应该更仔细地证明 OPs 代码。感谢您纠正我。
      猜你喜欢
      • 1970-01-01
      • 2012-07-09
      • 2016-01-11
      • 1970-01-01
      • 2017-02-26
      • 2019-07-03
      • 2018-01-16
      • 2018-04-16
      • 1970-01-01
      相关资源
      最近更新 更多