Search code examples
swiftlocationmanager

LocationManager verify if location is valid?


I am making an app where I must know if the location is valid, not cached, and current.

It's an app that displays what are close to you (with database and stuff)

Every 10 seconds I fetch data from the net and display the new data in a tableView.


Let's say I'm near a shop, and the app displays "You are close to the shop"

I close the app, go home and when I open the app It displays still "You are close to the shop" even though I requested the location..

It is because it returns a cached value back first..

Okay, I'm not that dumb, so I fixed it:

(I save the valid locations into the userLocation object)

So when user closes the app and returns back, it checks if the location is too old.. if so, then the userLocation object gets cleared, and locationManager?.requestLocation() gets called

But still, in the didUpdateLocations functions it checks if the location is too old, and if NOT, aka it is new, then I do fetch new data from the net

// Location Functions
    func setupLocationManager(){
        let authorizationStatus = CLLocationManager.authorizationStatus()
        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.requestAlwaysAuthorization()
        locationManager?.startUpdatingLocation() // Log only significant location changes
        locationManager?.pausesLocationUpdatesAutomatically = true // If user is not moving, don't update location
        locationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters // Ten meter accuracy
        locationManager?.distanceFilter = 20 // Update location only if 20m location change
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        currentLocation = locations.last

        // Check if location is not too old.. (aka cached)
        let locationIsValid:Bool = Date().timeIntervalSince(currentLocation!.timestamp) < 11
        if locationIsValid
        {
            currentLocationValue = currentLocation?.coordinate

            // If first loc after opening / returning to app, then fetch data
            if (userLocation.latitude == nil && userLocation.longitude == nil){

                userLocation.location = currentLocation
                userLocation.latitude = currentLocationValue?.latitude
                userLocation.longitude = currentLocationValue?.longitude

                mainFetchData()
            }

            userLocation.location = currentLocation
            userLocation.latitude = currentLocationValue?.latitude
            userLocation.longitude = currentLocationValue?.longitude
        }
    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        // Error so remove global variable user location
        userLocation.location = nil
        userLocation.latitude = nil
        userLocation.longitude = nil
    }

    // THIS GETS CALLED EVERYTIME applicationDidBecomeActive !
    @objc func notification_validateCachedLocation(){
        if userLocation.location != nil {
            let lastCachedLocationIsInvalid:Bool = Date().timeIntervalSince(userLocation.location!.timestamp) > 10
            if lastCachedLocationIsInvalid
            {
                userLocation.location = nil
                userLocation.latitude = nil
                userLocation.longitude = nil
                locationManager?.requestLocation()
            }

        } else {
            locationManager?.requestLocation()
        }
    }

But still there's a problem:

Let's say You're just home... you open the app, and it saves your location. You then close it.

Okay, so after siting for like 20 minutes, you return back and open the app again..

then the LocationManager loads the locations and because you haven't moved since, it doesn't get updated. And because of that, it will be older than 10 seconds, it will be just a cached location and therefore my app will not fetch data :C


Solution

  • Seems to me you should stop using pausesLocationUpdatesAutomatically and just manually pause it (stop locating) at times that suit you.