跟踪一定距离内的位置变化 iOS
Track changes in the location for a certain distance iOS
我有一个任务是在后台跟踪用户的位置,如果它的位置已经改变到超过 5 英里,那么我需要在服务器上更新这个数据。我知道您可以使用 startMonitoringSignificantLocationChanges 开始跟踪用户位置。我开始测试,使用 startMonitoringSignificantLocationChanges
和 allowsBackgroundLocationUpdates = true
启动应用程序,然后从模拟器内存中删除应用程序,进入地图并启用 Free Way 模拟。一分钟我在服务器上获得了 8 个更新,对我来说太频繁了。我认为对我来说,最好的解决方案是询问我们希望从多远的地方接收更新。我读了一些关于这个的帖子,但没有一个没有解决我的问题。我还认为您可以保存以前的位置并将更改与新位置进行比较,但我认为这是个坏主意。告诉我,如何更好地解决这个问题?
class LocationManager: NSObject {
private override init() {
super.init()
}
static let shared = LocationManager()
private let locationManager = CLLocationManager()
weak var delegate: LocationManagerDelegate?
// MARK: - Flags
private var isCallDidStartGetLocation = false
// MARK: - Measuring properties
private var startTimestamp = 0.0
// MARK: - Open data
var currentLocation: CLLocation?
// MARK: - Managers
private let locationDatabaseManager = LocationDatabaseManager()
// MARK: - Values
private let metersPerMile = 1609.34
func start() {
// measuring data
startTimestamp = Date().currentTimestamp
FirebasePerformanceManager.shared.getUserLocation(true)
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.activityType = .other
locationManager.distanceFilter = 100
locationManager.delegate = self
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedAlways:
locationManager.startUpdatingLocation()
case .authorizedWhenInUse:
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
case .restricted, .notDetermined:
locationManager.requestAlwaysAuthorization()
case .denied:
showNoPermissionsAlert()
}
}
func logOut() {
locationManager.stopUpdatingLocation()
isCallDidStartGetLocation = false
}
}
// MARK: - Alerts
extension LocationManager {
private func showNoPermissionsAlert() {
guard let topViewController = UIApplication.topViewController() else { return }
let alertController = UIAlertController(title: "No permission",
message: "In order to work, app needs your location", preferredStyle: .alert)
let openSettings = UIAlertAction(title: "Open settings", style: .default, handler: {
(action) -> Void in
guard let URL = Foundation.URL(string: UIApplicationOpenSettingsURLString) else { return }
UIApplication.shared.open(URL, options: [:], completionHandler: nil)
})
alertController.addAction(openSettings)
topViewController.present(alertController, animated: true, completion: nil)
}
}
// MARK: - CLLocationManager Delegate
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse, .authorizedAlways:
locationManager.startUpdatingLocation()
default: break
}
delegate?.didChangeAuthorization?(manager: manager, didChangeAuthorization: status)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let lastLocation = locations.last else { return }
let timeInterval = abs(lastLocation.timestamp.timeIntervalSinceNow)
guard timeInterval < 60 else { return }
currentLocation = lastLocation
locationDatabaseManager.updateUserLocation(lastLocation)
measureGetLocationTime()
if !isCallDidStartGetLocation {
isCallDidStartGetLocation = true
delegate?.didStartGetLocation?()
}
}
}
// MARK: - Calculation
extension LocationManager {
func calculateDistanceFromCurrentLocation(_ venueLocation: CLLocation) -> Double {
guard let userLocation = locationManager.location else {
return 0.0
}
let distance = userLocation.distance(from: venueLocation)
let distanceMiles = distance / DistanceConvertor.metersPerMile //1609
return distanceMiles.roundToPlaces(places: 1)
}
}
// MARK: - Measuring functions
extension LocationManager {
private func measureGetLocationTime() {
FirebasePerformanceManager.shared.getUserLocation(false)
let endTimestamp = Date().currentTimestamp
let resultTimestamp = endTimestamp - startTimestamp
BugfenderManager.getFirstUserLocation(resultTimestamp)
}
}
根据Apple Docs:
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
startMonitoringSignificantLocationChanges()
是最不准确的位置监控方式,并且无法配置它在手机信号塔转换时触发的频率。因此它可以在塔(城市)更密集的地区更频繁地触发。有关详细信息,请参阅 this thread。
我更改了当前的 LocationManager
并为此案例创建了两个新的管理器。我测试了应用程序,在我的更改之后,结果如下:我开了 120-130 公里,两个路段在城市之间,应用程序花费了设备费用的 1%,对我们来说这是一个可以接受的结果。应用程序向服务器发送了 4 次用户位置更新请求,条件如下:上次更新位置后耗时 2 小时,并且之前位置与新位置之间的距离为 5 英里或更多。您可以在下面看到实现。
位置管理器
import Foundation
import CoreLocation
class LocationManager: NSObject {
private override init() {
super.init()
manager.delegate = self
}
static let shared = LocationManager()
private let manager = CLLocationManager()
weak var delegate: LocationManagerDelegate?
// MARK: - Enums
enum DistanceValue: Int {
case meters, miles
}
// MARK: - Flags
private var isCallDidStartGetLocation = false
// MARK: - Measuring properties
private var startTimestamp = 0.0
// MARK: - Open data
var currentLocation: CLLocation?
// MARK: - Managers
private let locationDatabaseManager = LocationDatabaseManager()
// MARK: - Values
private let metersPerMile = 1609.34
func start() {
// measuring data
startTimestamp = Date().currentTimestamp
FirebasePerformanceManager.shared.getUserLocation(true)
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
manager.activityType = .other
manager.desiredAccuracy = 45
manager.distanceFilter = 100
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedAlways:
if UIApplication.shared.applicationState != .background {
manager.startUpdatingLocation()
}
manager.startMonitoringSignificantLocationChanges()
manager.allowsBackgroundLocationUpdates = true
case .authorizedWhenInUse:
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
case .restricted, .notDetermined:
manager.requestAlwaysAuthorization()
case .denied:
showNoPermissionsAlert()
}
}
func logOut() {
manager.stopUpdatingLocation()
isCallDidStartGetLocation = false
}
}
// MARK: - Mode managing
extension LocationManager {
open func enterBackground() {
manager.stopUpdatingLocation()
manager.startMonitoringSignificantLocationChanges()
}
open func enterForeground() {
manager.startUpdatingLocation()
}
}
// MARK: - Alerts
extension LocationManager {
private func showNoPermissionsAlert() {
guard let topViewController = UIApplication.topViewController() else { return }
let alertController = UIAlertController(title: "No permission",
message: "In order to work, app needs your location", preferredStyle: .alert)
let openSettings = UIAlertAction(title: "Open settings", style: .default, handler: {
(action) -> Void in
guard let URL = Foundation.URL(string: UIApplicationOpenSettingsURLString) else { return }
UIApplication.shared.open(URL, options: [:], completionHandler: nil)
})
alertController.addAction(openSettings)
topViewController.present(alertController, animated: true, completion: nil)
}
}
// MARK: - CLLocationManager Delegate
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse, .authorizedAlways:
if UIApplication.shared.applicationState != .background {
manager.startUpdatingLocation()
}
default: break
}
delegate?.didChangeAuthorization?(manager: manager, didChangeAuthorization: status)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let lastLocation = locations.last else { return }
let applicationState = UIApplication.shared.applicationState
switch applicationState {
case .active, .inactive:
activeAppGetLocation(lastLocation)
case .background:
backgroundAppGetLocation(lastLocation)
}
}
}
// MARK: - Gettings location functions
extension LocationManager {
private func activeAppGetLocation(_ location: CLLocation) {
let timeInterval = abs(location.timestamp.timeIntervalSinceNow)
guard timeInterval < 60 else { return }
currentLocation = location
locationDatabaseManager.updateUserLocation(location, state: .active)
if !isCallDidStartGetLocation {
measureGetLocationTime()
isCallDidStartGetLocation = true
delegate?.didStartGetLocation?()
}
}
private func backgroundAppGetLocation(_ location: CLLocation) {
let locationBackgroundManager = LocationBackgroundManager()
locationBackgroundManager.updateLocationInBackgroundIfNeeded(location)
}
}
// MARK: - Calculation
extension LocationManager {
func calculateDistanceBetweenLocations(_ firstLocation: CLLocation, secondLocation: CLLocation, valueType: DistanceValue) -> Double {
let meters = firstLocation.distance(from: secondLocation)
switch valueType {
case .meters:
return meters
case .miles:
let miles = meters / DistanceConvertor.metersPerMile
return miles
}
}
/// In miles
func calculateDistanceFromCurrentLocation(_ venueLocation: CLLocation) -> Double {
guard let userLocation = manager.location else {
return 0.0
}
let distance = userLocation.distance(from: venueLocation)
let distanceMiles = distance / DistanceConvertor.metersPerMile //1609
return distanceMiles.roundToPlaces(places: 1)
}
}
// MARK: - Measuring functions
extension LocationManager {
private func measureGetLocationTime() {
FirebasePerformanceManager.shared.getUserLocation(false)
let endTimestamp = Date().currentTimestamp
let resultTimestamp = endTimestamp - startTimestamp
BugfenderManager.getFirstUserLocation(resultTimestamp)
}
}
位置背景管理器
import Foundation
import CoreLocation
import SwiftDate
class LocationBackgroundManager {
private var backgroundLocationUpdateTimestamp: Double {
get {
return UserDefaults.standard.double(forKey: "backgroundLocationUpdateTimestamp")
}
set {
UserDefaults.standard.set(newValue, forKey: "backgroundLocationUpdateTimestamp")
UserDefaults.standard.synchronize()
}
}
// MARK: - Managers
private lazy var locationStorageManager: LocationStorageManager = {
let locationStorageManager = LocationStorageManager()
return locationStorageManager
}()
open func updateLocationInBackgroundIfNeeded(_ location: CLLocation) {
if backgroundLocationUpdateTimestamp != 0 {
let currentLocationDate = location.timestamp
let previousDate = Date(timeIntervalSince1970: backgroundLocationUpdateTimestamp)
guard let hours = (currentLocationDate - previousDate).in(.hour) else { return }
guard hours >= 2 else { return }
if let previousLocationRealm = locationStorageManager.getCurrentUserPreviousLocation() {
let previousLocation = CLLocation(latitude: previousLocationRealm.latitude, longitude: previousLocationRealm.longitude)
let distance = LocationManager.shared.calculateDistanceBetweenLocations(location, secondLocation: previousLocation, valueType: .miles)
guard distance >= 5 else { return }
updateLocation(location)
} else {
updateLocation(location)
}
} else {
updateLocation(location)
}
}
private func updateLocation(_ location: CLLocation) {
let locationDatabaseManager = LocationDatabaseManager()
locationDatabaseManager.updateUserLocation(location, state: .background)
backgroundLocationUpdateTimestamp = location.timestamp.currentTimestamp
locationStorageManager.saveLocation(location)
}
}
位置存储管理器
import Foundation
import CoreLocation
import RealmSwift
class LocationStorageManager {
func saveLocation(_ location: CLLocation) {
guard let currentUserID = RealmManager().getCurrentUser()?.id else { return }
let altitude = location.altitude
let latitude = location.coordinate.latitude
let longitude = location.coordinate.longitude
let locationRealm = LocationRealm(altitude: altitude, latitude: latitude, longitude: longitude, userID: currentUserID)
do {
let realm = try Realm()
try realm.write {
realm.add(locationRealm, update: true)
}
} catch {
debugPrint(error)
let funcName = #function
let file = #file
BugfenderManager.reportError(funcName, fileName: file, error: error)
}
}
func getCurrentUserPreviousLocation() -> LocationRealm? {
guard let currentUserID = RealmManager().getCurrentUser()?.id else { return nil }
do {
let realm = try Realm()
let previousLocation = realm.objects(LocationRealm.self).filter("userID == %@", currentUserID).first
return previousLocation
} catch {
debugPrint(error)
let funcName = #function
let file = #file
BugfenderManager.reportError(funcName, fileName: file, error: error)
return nil
}
}
}
我有一个任务是在后台跟踪用户的位置,如果它的位置已经改变到超过 5 英里,那么我需要在服务器上更新这个数据。我知道您可以使用 startMonitoringSignificantLocationChanges 开始跟踪用户位置。我开始测试,使用 startMonitoringSignificantLocationChanges
和 allowsBackgroundLocationUpdates = true
启动应用程序,然后从模拟器内存中删除应用程序,进入地图并启用 Free Way 模拟。一分钟我在服务器上获得了 8 个更新,对我来说太频繁了。我认为对我来说,最好的解决方案是询问我们希望从多远的地方接收更新。我读了一些关于这个的帖子,但没有一个没有解决我的问题。我还认为您可以保存以前的位置并将更改与新位置进行比较,但我认为这是个坏主意。告诉我,如何更好地解决这个问题?
class LocationManager: NSObject {
private override init() {
super.init()
}
static let shared = LocationManager()
private let locationManager = CLLocationManager()
weak var delegate: LocationManagerDelegate?
// MARK: - Flags
private var isCallDidStartGetLocation = false
// MARK: - Measuring properties
private var startTimestamp = 0.0
// MARK: - Open data
var currentLocation: CLLocation?
// MARK: - Managers
private let locationDatabaseManager = LocationDatabaseManager()
// MARK: - Values
private let metersPerMile = 1609.34
func start() {
// measuring data
startTimestamp = Date().currentTimestamp
FirebasePerformanceManager.shared.getUserLocation(true)
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.activityType = .other
locationManager.distanceFilter = 100
locationManager.delegate = self
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedAlways:
locationManager.startUpdatingLocation()
case .authorizedWhenInUse:
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
case .restricted, .notDetermined:
locationManager.requestAlwaysAuthorization()
case .denied:
showNoPermissionsAlert()
}
}
func logOut() {
locationManager.stopUpdatingLocation()
isCallDidStartGetLocation = false
}
}
// MARK: - Alerts
extension LocationManager {
private func showNoPermissionsAlert() {
guard let topViewController = UIApplication.topViewController() else { return }
let alertController = UIAlertController(title: "No permission",
message: "In order to work, app needs your location", preferredStyle: .alert)
let openSettings = UIAlertAction(title: "Open settings", style: .default, handler: {
(action) -> Void in
guard let URL = Foundation.URL(string: UIApplicationOpenSettingsURLString) else { return }
UIApplication.shared.open(URL, options: [:], completionHandler: nil)
})
alertController.addAction(openSettings)
topViewController.present(alertController, animated: true, completion: nil)
}
}
// MARK: - CLLocationManager Delegate
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse, .authorizedAlways:
locationManager.startUpdatingLocation()
default: break
}
delegate?.didChangeAuthorization?(manager: manager, didChangeAuthorization: status)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let lastLocation = locations.last else { return }
let timeInterval = abs(lastLocation.timestamp.timeIntervalSinceNow)
guard timeInterval < 60 else { return }
currentLocation = lastLocation
locationDatabaseManager.updateUserLocation(lastLocation)
measureGetLocationTime()
if !isCallDidStartGetLocation {
isCallDidStartGetLocation = true
delegate?.didStartGetLocation?()
}
}
}
// MARK: - Calculation
extension LocationManager {
func calculateDistanceFromCurrentLocation(_ venueLocation: CLLocation) -> Double {
guard let userLocation = locationManager.location else {
return 0.0
}
let distance = userLocation.distance(from: venueLocation)
let distanceMiles = distance / DistanceConvertor.metersPerMile //1609
return distanceMiles.roundToPlaces(places: 1)
}
}
// MARK: - Measuring functions
extension LocationManager {
private func measureGetLocationTime() {
FirebasePerformanceManager.shared.getUserLocation(false)
let endTimestamp = Date().currentTimestamp
let resultTimestamp = endTimestamp - startTimestamp
BugfenderManager.getFirstUserLocation(resultTimestamp)
}
}
根据Apple Docs:
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
startMonitoringSignificantLocationChanges()
是最不准确的位置监控方式,并且无法配置它在手机信号塔转换时触发的频率。因此它可以在塔(城市)更密集的地区更频繁地触发。有关详细信息,请参阅 this thread。
我更改了当前的 LocationManager
并为此案例创建了两个新的管理器。我测试了应用程序,在我的更改之后,结果如下:我开了 120-130 公里,两个路段在城市之间,应用程序花费了设备费用的 1%,对我们来说这是一个可以接受的结果。应用程序向服务器发送了 4 次用户位置更新请求,条件如下:上次更新位置后耗时 2 小时,并且之前位置与新位置之间的距离为 5 英里或更多。您可以在下面看到实现。
位置管理器
import Foundation
import CoreLocation
class LocationManager: NSObject {
private override init() {
super.init()
manager.delegate = self
}
static let shared = LocationManager()
private let manager = CLLocationManager()
weak var delegate: LocationManagerDelegate?
// MARK: - Enums
enum DistanceValue: Int {
case meters, miles
}
// MARK: - Flags
private var isCallDidStartGetLocation = false
// MARK: - Measuring properties
private var startTimestamp = 0.0
// MARK: - Open data
var currentLocation: CLLocation?
// MARK: - Managers
private let locationDatabaseManager = LocationDatabaseManager()
// MARK: - Values
private let metersPerMile = 1609.34
func start() {
// measuring data
startTimestamp = Date().currentTimestamp
FirebasePerformanceManager.shared.getUserLocation(true)
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
manager.activityType = .other
manager.desiredAccuracy = 45
manager.distanceFilter = 100
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedAlways:
if UIApplication.shared.applicationState != .background {
manager.startUpdatingLocation()
}
manager.startMonitoringSignificantLocationChanges()
manager.allowsBackgroundLocationUpdates = true
case .authorizedWhenInUse:
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
case .restricted, .notDetermined:
manager.requestAlwaysAuthorization()
case .denied:
showNoPermissionsAlert()
}
}
func logOut() {
manager.stopUpdatingLocation()
isCallDidStartGetLocation = false
}
}
// MARK: - Mode managing
extension LocationManager {
open func enterBackground() {
manager.stopUpdatingLocation()
manager.startMonitoringSignificantLocationChanges()
}
open func enterForeground() {
manager.startUpdatingLocation()
}
}
// MARK: - Alerts
extension LocationManager {
private func showNoPermissionsAlert() {
guard let topViewController = UIApplication.topViewController() else { return }
let alertController = UIAlertController(title: "No permission",
message: "In order to work, app needs your location", preferredStyle: .alert)
let openSettings = UIAlertAction(title: "Open settings", style: .default, handler: {
(action) -> Void in
guard let URL = Foundation.URL(string: UIApplicationOpenSettingsURLString) else { return }
UIApplication.shared.open(URL, options: [:], completionHandler: nil)
})
alertController.addAction(openSettings)
topViewController.present(alertController, animated: true, completion: nil)
}
}
// MARK: - CLLocationManager Delegate
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedWhenInUse, .authorizedAlways:
if UIApplication.shared.applicationState != .background {
manager.startUpdatingLocation()
}
default: break
}
delegate?.didChangeAuthorization?(manager: manager, didChangeAuthorization: status)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let lastLocation = locations.last else { return }
let applicationState = UIApplication.shared.applicationState
switch applicationState {
case .active, .inactive:
activeAppGetLocation(lastLocation)
case .background:
backgroundAppGetLocation(lastLocation)
}
}
}
// MARK: - Gettings location functions
extension LocationManager {
private func activeAppGetLocation(_ location: CLLocation) {
let timeInterval = abs(location.timestamp.timeIntervalSinceNow)
guard timeInterval < 60 else { return }
currentLocation = location
locationDatabaseManager.updateUserLocation(location, state: .active)
if !isCallDidStartGetLocation {
measureGetLocationTime()
isCallDidStartGetLocation = true
delegate?.didStartGetLocation?()
}
}
private func backgroundAppGetLocation(_ location: CLLocation) {
let locationBackgroundManager = LocationBackgroundManager()
locationBackgroundManager.updateLocationInBackgroundIfNeeded(location)
}
}
// MARK: - Calculation
extension LocationManager {
func calculateDistanceBetweenLocations(_ firstLocation: CLLocation, secondLocation: CLLocation, valueType: DistanceValue) -> Double {
let meters = firstLocation.distance(from: secondLocation)
switch valueType {
case .meters:
return meters
case .miles:
let miles = meters / DistanceConvertor.metersPerMile
return miles
}
}
/// In miles
func calculateDistanceFromCurrentLocation(_ venueLocation: CLLocation) -> Double {
guard let userLocation = manager.location else {
return 0.0
}
let distance = userLocation.distance(from: venueLocation)
let distanceMiles = distance / DistanceConvertor.metersPerMile //1609
return distanceMiles.roundToPlaces(places: 1)
}
}
// MARK: - Measuring functions
extension LocationManager {
private func measureGetLocationTime() {
FirebasePerformanceManager.shared.getUserLocation(false)
let endTimestamp = Date().currentTimestamp
let resultTimestamp = endTimestamp - startTimestamp
BugfenderManager.getFirstUserLocation(resultTimestamp)
}
}
位置背景管理器
import Foundation
import CoreLocation
import SwiftDate
class LocationBackgroundManager {
private var backgroundLocationUpdateTimestamp: Double {
get {
return UserDefaults.standard.double(forKey: "backgroundLocationUpdateTimestamp")
}
set {
UserDefaults.standard.set(newValue, forKey: "backgroundLocationUpdateTimestamp")
UserDefaults.standard.synchronize()
}
}
// MARK: - Managers
private lazy var locationStorageManager: LocationStorageManager = {
let locationStorageManager = LocationStorageManager()
return locationStorageManager
}()
open func updateLocationInBackgroundIfNeeded(_ location: CLLocation) {
if backgroundLocationUpdateTimestamp != 0 {
let currentLocationDate = location.timestamp
let previousDate = Date(timeIntervalSince1970: backgroundLocationUpdateTimestamp)
guard let hours = (currentLocationDate - previousDate).in(.hour) else { return }
guard hours >= 2 else { return }
if let previousLocationRealm = locationStorageManager.getCurrentUserPreviousLocation() {
let previousLocation = CLLocation(latitude: previousLocationRealm.latitude, longitude: previousLocationRealm.longitude)
let distance = LocationManager.shared.calculateDistanceBetweenLocations(location, secondLocation: previousLocation, valueType: .miles)
guard distance >= 5 else { return }
updateLocation(location)
} else {
updateLocation(location)
}
} else {
updateLocation(location)
}
}
private func updateLocation(_ location: CLLocation) {
let locationDatabaseManager = LocationDatabaseManager()
locationDatabaseManager.updateUserLocation(location, state: .background)
backgroundLocationUpdateTimestamp = location.timestamp.currentTimestamp
locationStorageManager.saveLocation(location)
}
}
位置存储管理器
import Foundation
import CoreLocation
import RealmSwift
class LocationStorageManager {
func saveLocation(_ location: CLLocation) {
guard let currentUserID = RealmManager().getCurrentUser()?.id else { return }
let altitude = location.altitude
let latitude = location.coordinate.latitude
let longitude = location.coordinate.longitude
let locationRealm = LocationRealm(altitude: altitude, latitude: latitude, longitude: longitude, userID: currentUserID)
do {
let realm = try Realm()
try realm.write {
realm.add(locationRealm, update: true)
}
} catch {
debugPrint(error)
let funcName = #function
let file = #file
BugfenderManager.reportError(funcName, fileName: file, error: error)
}
}
func getCurrentUserPreviousLocation() -> LocationRealm? {
guard let currentUserID = RealmManager().getCurrentUser()?.id else { return nil }
do {
let realm = try Realm()
let previousLocation = realm.objects(LocationRealm.self).filter("userID == %@", currentUserID).first
return previousLocation
} catch {
debugPrint(error)
let funcName = #function
let file = #file
BugfenderManager.reportError(funcName, fileName: file, error: error)
return nil
}
}
}