Swift 获取位置然后加载 table

Swift get location THEN load table

所以我想在用户第一次打开应用程序时询问他们的位置,然后加载 table。这是我现在的代码:

class LayoutController: UICollectionViewController, UICollectionViewDataSource,
UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, 
APIControllerProtocol, CLLocationManagerDelegate {


    @IBOutlet weak var chainTable: UICollectionView!
    @IBOutlet weak var navLogo: UIButton!
    let locationManager : CLLocationManager = CLLocationManager()

    var lat: String = "lat!"
    var long: String = "long!"


    override func viewDidLoad() {
        super.viewDidLoad()
        UIApplication.sharedApplication().statusBarStyle = .LightContent
        navLogo.userInteractionEnabled = false

        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        if( CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedWhenInUse || CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedAlways){
            var currentLocation = locationManager.location
            var longitude = currentLocation.coordinate.longitude
            var latitude = currentLocation.coordinate.latitude

            long = String(stringInterpolationSegment: longitude)
            lat = String(stringInterpolationSegment: latitude)
        }
        // Do any additional setup after loading the view.            
        loadTable(lat, longitude, long)
    }

    func loadTable(latitude: String, longitude: String){
        api = APIController(delegate: self)
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
        api!.getPosts(latitude, longitude: longitude)
    }
}

首次下载和启用位置后数据未正确加载。但是,当您重新启动应用程序时,我确实可以工作。如何让 table 在加载前检查位置是否已给出?谢谢

(我已经尝试在 if CLLocationManager.authorizationstatus()... 块中使用 loadTable 函数,但也无济于事。)

需要监听CLLocationManagerDelegate的委托方法:

locationManager:didUpdateLocations:

在获得成功结果后,设置并重新加载 table 视图的数据。

正如@dimpiax 所暗示的那样,您的做法是错误的。

位置管理器是异步的API。一旦你确定你被授权使用它,你就要求它开始更新你的位置。然后你等待它调用你的委托方法 locationManager:didUpdateLocations:.

即使那样你还没有完成。通常你得到的第一个位置是旧的,而且非常非常错误。 (这是 GPS 上次激活时读取的位置。)您必须检查该位置的时间戳,如果时间戳超过几秒则忽略它。

但是等等,您仍然没有完成。一旦你放弃了一个可能过时的位置,你需要等到 GPS 稳定下来并开始提供合适的读数。在您请求位置更新后的前 5 秒或更长时间,读数的误差范围通常非常糟糕。您可以通过检查您获得的位置记录上的水平精度 属性 来解决这个问题。该值实际上是一个半径。大数字不好,小数字好。您可能需要水平精度 <= 100 米的读数。

完成后,您就可以重新加载 table 视图了。

多亏了 Duncan 和 this tutorial

我弄明白了

func locationManager(管理器:CLLocationManager!,didUpdateLocations 位置:[AnyObject]!){

    CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placemarks, error) -> Void in

        if (error != nil){
            println("Error:" + error.localizedDescription)
        }

        if placemarks.count > 0 {
            let pm = placemarks[0] as! CLPlacemark

            if( CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedWhenInUse || CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedAlways){
                var currentLocation = self.locationManager.location
                var longitude = currentLocation.coordinate.longitude
                var latitude = currentLocation.coordinate.latitude

                self.long = String(stringInterpolationSegment: longitude)
                self.lat = String(stringInterpolationSegment: latitude)
            }

            self.displayLocationInfo(pm)
            self.loadTable(self.lat, longitude: self.long)
        }else{
            println("error with data")
        }

    })

我将其添加到 viewDidLoad 的正下方,并将 Auth 块移入其中。

我创建了一个 class 来获取用户的当前位置并 return 它在一个块中。

class NACurrentLocationTrackManager: NSObject,CLLocationManagerDelegate {
    var locationManager: CLLocationManager?
     private static var privateShared : NACurrentLocationTrackManager?
    typealias completionHandler = (_ location: CLLocation?,_ error: String?) -> Void
    var completion: completionHandler?
    class func shared() -> NACurrentLocationTrackManager {
    guard let uwShared = privateShared else {
        privateShared = NACurrentLocationTrackManager()
        return privateShared!
    }
    return uwShared
}
class func destroy() {
    privateShared = nil
}
func stopLocationManager() {
    locationManager?.stopUpdatingLocation()
}
func startMonitoringLocationWithBlock(handler:@escaping (_ location: CLLocation?,_ error: String?) -> Void){
    self.completion = handler
    if locationManager == nil{
        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.desiredAccuracy = kCLLocationAccuracyBest
        locationManager?.requestAlwaysAuthorization()
    }
    locationManager?.stopUpdatingLocation()
    locationManager?.startUpdatingLocation()
}
func restartMonitoringLocation(){
    locationManager?.stopUpdatingLocation()
    if CLLocationManager.authorizationStatus() == .authorizedAlways ||  CLLocationManager.authorizationStatus() == .authorizedWhenInUse{
        locationManager?.startUpdatingLocation()
    }else if CLLocationManager.authorizationStatus() == .denied{
        logh("Location service is disable")
        NAAppHelper.showLocationPermissionAlert()
        locationManager?.requestAlwaysAuthorization()
    }else{
        locationManager?.requestAlwaysAuthorization()
    }
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
    let location = locations.last
    if let handler = completion {
        handler(location, nil)
    }
    stopLocationManager()
}
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        if let handler = completion {
            handler(nil, "")
        }
    }
 }
And to fetch the location, use this code in your viewcontroller:
    NACurrentLocationTrackManager.shared().startMonitoringLocationWithBlock { (location, error) in
        if error == nil {
            print(location)
        }
    }