BaseGeolocable example
// | |
// BaseGeolocable.swift | |
// | |
// Created by Juan Felipe Alvarez Saldarriaga on 11/11/16. | |
// | |
import Foundation | |
import CoreLocation | |
protocol BaseGeolocable: class, CLLocationManagerDelegate { | |
var currentLocation: CLLocation? { get set } | |
} | |
// MARK: - CLLocationManagerDelegate | |
extension BaseGeolocable { | |
func defaultLocationManager() -> CLLocationManager { | |
let manager = CLLocationManager() | |
manager.distanceFilter = kCLDistanceFilterNone | |
manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers | |
manager.delegate = self | |
manager.requestWhenInUseAuthorization() | |
return manager | |
} | |
func setCurrentLocationWith(manager: CLLocationManager, locations: [CLLocation], completion: (() -> Void)? = nil) { | |
guard let newLocation = locations.last else { | |
return | |
} | |
// see: http://stackoverflow.com/a/12848776/255463 | |
// | |
// test the age of the location measurement to determine if the measurement is cached | |
// in most cases you will not want to rely on cached measurements | |
let locationAge = -newLocation.timestamp.timeIntervalSinceNow | |
if locationAge > 5.0 { | |
return | |
} | |
// test that the horizontal accuracy does not indicate an invalid measurement | |
if newLocation.horizontalAccuracy < 0 { | |
return | |
} | |
// test the measurement to see if it is more accurate than the previous measurement | |
if currentLocation == nil || (currentLocation?.horizontalAccuracy)! > newLocation.horizontalAccuracy { | |
// store the location as the "best effort" | |
currentLocation = newLocation | |
// test the measurement to see if it meets the desired accuracy | |
// | |
// IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue | |
// accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of | |
// acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout. | |
// | |
if newLocation.horizontalAccuracy <= manager.desiredAccuracy { | |
// we have a measurement that meets our requirements, so we can stop updating the location | |
// | |
// IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible. | |
// | |
manager.stopUpdatingLocation() | |
} | |
} | |
if let completion = completion { | |
completion() | |
} | |
} | |
} |
// | |
// ServiceLocationViewController.swift | |
// | |
// Created by Juan Felipe Alvarez Saldarriaga on 10/27/16. | |
// | |
import UIKit | |
import CoreLocation | |
final class ServiceLocationViewController: UIViewController { | |
lazy var locationManager: CLLocationManager = self.defaultLocationManager() | |
var viewModel: ServiceLocationViewModelProtocol? { | |
willSet { | |
viewModel?.viewDelegate = nil | |
} | |
didSet { | |
viewModel?.viewDelegate = self | |
} | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
locationManager.startUpdatingLocation() | |
} | |
} | |
// MARK: - Load | |
extension ServiceLocationViewController { | |
func loadGeolocation() { | |
guard let currentLocation = currentLocation else { | |
return | |
} | |
viewModel?.currentLocation = currentLocation | |
viewModel?.geolocationParentType = .service | |
viewModel?.geolocation() | |
} | |
} | |
// MARK: - BaseGeolocable | |
extension ServiceLocationViewController: BaseGeolocable { | |
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { | |
// FIXME: implement geolocable error (jf) | |
} | |
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { | |
self.setCurrentLocationWith(manager: manager, locations: locations, completion: { [unowned self] in | |
self.loadGeolocation() | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment