Swift CLGeocoder 获取时区

Swift CLGeocoder to get TimeZone

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

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()
        }
    }
}

getTimeZone

中包含异步 reverseGeocodeLocation 时,为什么要尝试 return 一个值
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)
        }

你几乎是对的。去掉 return 值。您不能 return 像这样的异步函数的函数结果。

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

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)")
}

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

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)")
}