如何在 Swift viewDidLoad 中获取邮政编码?

How to get postal code in Swift viewDidLoad?

我是 Swift 的新手,我需要在 viewDidLoad() 中设置 var postalCode。正如您在下面的代码中看到的,我在 didUpdateLocations 中使用了反向地理编码位置,但由于它是异步的,因此 postalCode 变量未在 viewDidLoad() 中设置。我该怎么做?

ViewController.swift

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()
    var postalCode = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        println("Postal code is: \(self.postalCode)")
    }

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
        CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)-> Void in
            if error != nil {
                println("Reverse geocoder failed with error: \(error.localizedDescription)")
                return
            }

            if placemarks.count > 0 {
                let placemark = placemarks[0] as! CLPlacemark
                self.locationManager.stopUpdatingLocation()
                self.postalCode = (placemark.postalCode != nil) ? placemark.postalCode : ""
                println("Postal code updated to: \(self.postalCode)")
            }else{
                println("No placemarks found.")
            }
        })
    }

    func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
        println("Location manager error: \(error.localizedDescription)")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

实际上有两个连续的异步操作。首先是位置更新,然后是地理编码。您不想等待 viewDidLoad() 中的结果,因为这会导致糟糕的用户体验,并且可能 iOS 甚至会因应用程序无响应而将其从内存中逐出。

更改应用程序逻辑,以便在可用时使用 ZIP。例如,如果您想在 UI 中显示 ZIP,请在开始时将其留空并从 reverseGeocodeLocation 完成处理程序更新它。它会在可用时立即出现。

@MirekE 是正确的。您的 -viewDidLoad 方法不会等待位置管理器完成更新,然后等待地理编码器完成地理编码。它在设置 postalCode 的值之前记录消息 Postal code is:

解法:

将您需要的任何代码移动到 postalCode 上的自定义 didSet 触发器中:

var postalCode:String! = "" {
    didSet {
        println("Postal code is: \(self.postalCode)")
        // and whatever other code you need here.
    }
};