在不耗尽电池电量的情况下以良好的准确性获取位置更新的最佳方法
Best way to get LocationUpdates with a good Accuracy without draining down the Battery
我一直在尝试实现一个 LocationView 控制器,它不断将用户位置更新到服务器。当我调试应用程序并在使用时,我注意到,我提供的源代码比平时更快地耗尽了我的手机电池。我是否必须解决这个问题,或者有什么方法可以在不减少 LocationRequirements 的情况下改进以下代码中的 PowerUsage?
class LocationViewController: UIViewController {
// MARK: - Outlets
@IBOutlet var mapView: MKMapView!
fileprivate var locations = [MKPointAnnotation]()
var updatesEnabled: Bool = false;
var defaultCentre: NotificationCenter = NotificationCenter.default
//- NSUserDefaults - LocationServicesControl_KEY to be set to TRUE when user has enabled location services.
let UDefaults: UserDefaults = UserDefaults.standard;
let LocationServicesControl_KEY: String = "LocationServices"
public var lastPosition: Date?;
public lazy var locationManager: CLLocationManager = {
let manager = CLLocationManager()
manager.distanceFilter = 20;
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestAlwaysAuthorization()
return manager
}()
public var routeLine: MKPolyline = MKPolyline() //your line
public var routeLineView: MKPolylineView = MKPolylineView(); //overlay view
// MARK: - Actions
@available(iOS 9.0, *)
@IBAction func enabledChanged(_ sender: UISwitch) {
if sender.isOn {
self.UDefaults.set(true, forKey: self.LocationServicesControl_KEY)
locationManager.startUpdatingLocation()
locationManager.allowsBackgroundLocationUpdates = true
self.updatesEnabled = true;
} else {
self.UDefaults.set(false, forKey: self.LocationServicesControl_KEY)
locationManager.stopUpdatingLocation()
self.updatesEnabled = false;
self.timer.invalidate()
locationManager.allowsBackgroundLocationUpdates = false
}
}
@IBAction func accuracyChanged(_ sender: UISegmentedControl) {
let accuracyValues = [
kCLLocationAccuracyBestForNavigation,
kCLLocationAccuracyBest,
kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters,
kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometers]
locationManager.desiredAccuracy = accuracyValues[sender.selectedSegmentIndex];
}
// MARK: - Override UIViewController
override func viewDidLoad() {
mapView.delegate = self;
}
}
// MARK: - MKMapViewDelegate
extension LocationViewController: MKMapViewDelegate {
func addRoute() {
mapView.remove(self.routeLine);
var pointsToUse: [CLLocationCoordinate2D] = [];
for i in locations {
pointsToUse += [i.coordinate];
}
self.routeLine = MKPolyline(coordinates: &pointsToUse, count: pointsToUse.count)
mapView.add(self.routeLine)
}
}
// MARK: - CLLocationManagerDelegate
extension LocationViewController: CLLocationManagerDelegate {
func isUpdateValid (newDate: Date) -> Bool{
var interval = TimeInterval()
if(lastPosition==nil){lastPosition=newDate}
interval = newDate.timeIntervalSince(lastPosition!)
if ((interval==0)||(interval>=self.UpdatesInterval)){
return true
} else {
return false
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let mostRecentLocation = locations.last else {
return
}
if(isUpdateValid(newDate: mostRecentLocation.timestamp)){
let position = MKPointAnnotation();
position.coordinate=mostRecentLocation.coordinate;
self.locations.append(position);
self.addRoute();
self.locationAPI.postLocation(location: mostRecentLocation)
lastPosition=mostRecentLocation.timestamp
}
}
}
您需要限制使用 GPS "lit" 的时间。如果您将其设置为持续提供高精度 GPS 读数,它将使 GPS 保持通电状态,您将消耗大量电量。对此无能为力。
可能性:
您可以每 10 分钟唤醒一次 GPS,运行它直到您获得良好的读数,然后再将其关闭。
当您的应用程序首次启动时,您会获得很好的阅读,然后订阅重要的位置更改,当您获得更新时,开始位置更新,获得新的修复,然后再次关闭位置更新。
我不确定您会如何执行第一个选项,因为 Apple 不会让您的应用 运行 无限期地在后台运行。您需要您的应用程序处于唤醒状态并且 运行 一直在前台运行,这也比允许它进入睡眠状态更快地耗尽电池电量。
我一直在尝试实现一个 LocationView 控制器,它不断将用户位置更新到服务器。当我调试应用程序并在使用时,我注意到,我提供的源代码比平时更快地耗尽了我的手机电池。我是否必须解决这个问题,或者有什么方法可以在不减少 LocationRequirements 的情况下改进以下代码中的 PowerUsage?
class LocationViewController: UIViewController {
// MARK: - Outlets
@IBOutlet var mapView: MKMapView!
fileprivate var locations = [MKPointAnnotation]()
var updatesEnabled: Bool = false;
var defaultCentre: NotificationCenter = NotificationCenter.default
//- NSUserDefaults - LocationServicesControl_KEY to be set to TRUE when user has enabled location services.
let UDefaults: UserDefaults = UserDefaults.standard;
let LocationServicesControl_KEY: String = "LocationServices"
public var lastPosition: Date?;
public lazy var locationManager: CLLocationManager = {
let manager = CLLocationManager()
manager.distanceFilter = 20;
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestAlwaysAuthorization()
return manager
}()
public var routeLine: MKPolyline = MKPolyline() //your line
public var routeLineView: MKPolylineView = MKPolylineView(); //overlay view
// MARK: - Actions
@available(iOS 9.0, *)
@IBAction func enabledChanged(_ sender: UISwitch) {
if sender.isOn {
self.UDefaults.set(true, forKey: self.LocationServicesControl_KEY)
locationManager.startUpdatingLocation()
locationManager.allowsBackgroundLocationUpdates = true
self.updatesEnabled = true;
} else {
self.UDefaults.set(false, forKey: self.LocationServicesControl_KEY)
locationManager.stopUpdatingLocation()
self.updatesEnabled = false;
self.timer.invalidate()
locationManager.allowsBackgroundLocationUpdates = false
}
}
@IBAction func accuracyChanged(_ sender: UISegmentedControl) {
let accuracyValues = [
kCLLocationAccuracyBestForNavigation,
kCLLocationAccuracyBest,
kCLLocationAccuracyNearestTenMeters,
kCLLocationAccuracyHundredMeters,
kCLLocationAccuracyKilometer,
kCLLocationAccuracyThreeKilometers]
locationManager.desiredAccuracy = accuracyValues[sender.selectedSegmentIndex];
}
// MARK: - Override UIViewController
override func viewDidLoad() {
mapView.delegate = self;
}
}
// MARK: - MKMapViewDelegate
extension LocationViewController: MKMapViewDelegate {
func addRoute() {
mapView.remove(self.routeLine);
var pointsToUse: [CLLocationCoordinate2D] = [];
for i in locations {
pointsToUse += [i.coordinate];
}
self.routeLine = MKPolyline(coordinates: &pointsToUse, count: pointsToUse.count)
mapView.add(self.routeLine)
}
}
// MARK: - CLLocationManagerDelegate
extension LocationViewController: CLLocationManagerDelegate {
func isUpdateValid (newDate: Date) -> Bool{
var interval = TimeInterval()
if(lastPosition==nil){lastPosition=newDate}
interval = newDate.timeIntervalSince(lastPosition!)
if ((interval==0)||(interval>=self.UpdatesInterval)){
return true
} else {
return false
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let mostRecentLocation = locations.last else {
return
}
if(isUpdateValid(newDate: mostRecentLocation.timestamp)){
let position = MKPointAnnotation();
position.coordinate=mostRecentLocation.coordinate;
self.locations.append(position);
self.addRoute();
self.locationAPI.postLocation(location: mostRecentLocation)
lastPosition=mostRecentLocation.timestamp
}
}
}
您需要限制使用 GPS "lit" 的时间。如果您将其设置为持续提供高精度 GPS 读数,它将使 GPS 保持通电状态,您将消耗大量电量。对此无能为力。
可能性:
您可以每 10 分钟唤醒一次 GPS,运行它直到您获得良好的读数,然后再将其关闭。
当您的应用程序首次启动时,您会获得很好的阅读,然后订阅重要的位置更改,当您获得更新时,开始位置更新,获得新的修复,然后再次关闭位置更新。
我不确定您会如何执行第一个选项,因为 Apple 不会让您的应用 运行 无限期地在后台运行。您需要您的应用程序处于唤醒状态并且 运行 一直在前台运行,这也比允许它进入睡眠状态更快地耗尽电池电量。