Search code examples
swiftuicollectionviewcllocationmanageruicollectionviewcellcllocation

Swift get location THEN load table


So I want to ask a user for their location when they open the app for the first time and THEN load the table. Here's my present code:

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

The data doesn't properly load on the first download and after location is enabled. I does work when you restart the app however. How can I make the table check if the location is given before loading? Thanks.

(I have tried it with the loadTable function inside the if CLLocationManager.authorizationstatus()... block to no avail either.)


Solution

  • As @dimpiax suggests, you're going about this wrong.

    The location manager is an asynchronous API. Once you make sure you are authorized to use it, you ask it to start updating your location. Then you wait for it to call your delegate method locationManager:didUpdateLocations:.

    Even then you're not done. Usually the first location you get is old and very, very wrong. (It is the location that was read when the GPS was last active.) You have to check the timestamp on that location and ignore it if it's timestamp is more than a few seconds old.

    But wait, you're still not done. Once you've thrown away a possible out-of-date location, you need to wait until the GPS settles down and starts giving decent readings. For the first 5 or more seconds after you ask for location updates, the margin of error on the readings is usually very bad. You figure this out by checking the horizontal accuracy property on the location record you get. The value is actually a radius. Large numbers are bad, small numbers are good. You probably want a reading with a horizontal accuracy of <= 100 meters.

    Once you've got that, you're ready to reload your table view.