Skip to content

Instantly share code, notes, and snippets.

@nebiros
Last active January 5, 2017 22:41
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save nebiros/9c928e98e0115382ad38f4dd6c0f3639 to your computer and use it in GitHub Desktop.
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