Skip to content

Instantly share code, notes, and snippets.

@Hadevs
Created November 23, 2020 16:26
Show Gist options
  • Save Hadevs/604fc56db3249ed18d9272352b34de4f to your computer and use it in GitHub Desktop.
Save Hadevs/604fc56db3249ed18d9272352b34de4f to your computer and use it in GitHub Desktop.
import UIKit
import CoreLocation
class LocationProvider: NSObject, CLLocationManagerDelegate {
static let shared = LocationProvider()
var city: String?
var currentLocation: CLLocation?
var lastRealOneLocation: CLLocation?
private var locationList: [CLLocation] = []
private let locationManager = CLLocationManager()
var subscribe: ((CLLocation) -> Void)?
private(set) var distance: Measurement<UnitLength> = .init(value: 0, unit: .meters)
func requestPermissions() {
locationManager.allowsBackgroundLocationUpdates = true
locationManager.showsBackgroundLocationIndicator = true
locationManager.delegate = self
locationManager.activityType = .fitness
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
func resetDistance() {
distance = .init(value: 0, unit: .meters)
}
func startFetchingLocation() {
locationManager.startUpdatingLocation()
}
func forceRequestSubcribe() {
guard let myLocation = currentLocation else {
return
}
subscribe?(myLocation)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
var lastLocationDate: Date?
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else {
return
}
self.lastRealOneLocation = location
let speed = location.speed * 3.6 // km/h
let time = Date().timeIntervalSince(lastLocationDate ?? Date()) / 60 / 60 // h
let maxDistance = time * speed // km
let newLocation = locations.sorted {
$0.horizontalAccuracy < $1.horizontalAccuracy
}.first!
if let lastLocation = locationList.last {
let delta = newLocation.distance(from: lastLocation)
let newDistance = Measurement(value: delta, unit: UnitLength.meters)
// UIApplication.shared.keyWindow?.makeToast("\(maxDistance), \(newDistance.value / 1000)")
let coeff: Double = 0.75
if (newDistance.value / 1000) * coeff > maxDistance {
// new Distance should not be over than maxDistance
return
}
distance = distance + newDistance
}
locationList.append(newLocation)
subscribe?(location)
self.currentLocation = location
self.lastLocationDate = Date()
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
if let placemark = placemarks?.first {
self.city = placemark.locality
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment