我已经在我的应用中实现了 CLLocationManager 的区域监控功能,它可以工作但它会耗尽我的电池:
-
-
应该这样吗?
我的代码:
monitorLocationViewController.m(请滚动查看完整代码):
-(void)locationManagerCLLocationManager *)manager didUpdateLocationsNSArray<CLLocation *> *)locations
{
//If "allStores"(NSMutableArray) isn't nil - calling "locationChangeHandler" to update monitoring
if (self.allStores!=nil) {
[self locationChangeHandler];
}
CLLocation *currentLocation=(CLLocation*)[locations lastObject];
NSSet *monitoredRegionsSet=self.locationManager.monitoredRegions;
[monitoredRegionsSet enumerateObjectsUsingBlock:^(CLCircularRegion *region, BOOL *stop) {
if ([region containsCoordinate:currentLocation.coordinate]) {
[self.locationManager stopMonitoringForRegion:region];
[self locationManager:self.locationManager didEnterRegion:region];
}
}];
}
-(void)locationManagerCLLocationManager *)manager didEnterRegionCLRegion *)region
{
Store *store=[self storeForRegion:region];
if (store.alreadySendNotification==NO) {
UILocalNotification *notification=[[UILocalNotification alloc] init];
notification.alertTitle=@"Arounder";
notification.alertBody=[[self storeForRegion:region] address];
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
store.alreadySendNotification=YES;
}
}
//For updating monitoring
-(void)locationChangeHandler
{
//If "allStores"(NSMutableArray) isn't nil
if (self.allStores!=nil) {
//Finding the 20 closest stores to he user's location and adding it to "twentyClosestStores"(NSMutableArray)
[self sortClosestStores];
//Stop monitoring "previousTwentyStores"(NSMutableArray) (20 closest stores before user's location updated)
[self stopMonitoringStores];
//Start monitoring "twentyClosestStores"(NSMutableArray)
[self startMonitoringClosestStores];
}
}
//Start monitoring "twentyClosestStores"(NSMutableArray)
-(void)startMonitoringClosestStores
{
//If monitoring isn't availible for "CLCircularRegion"
if (![CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) {
NSLog(@"Monitoring is not available for CLCircularRegion class");
return;
}
//Run on all "twentyClosestStores"(NSMutableArray)'s objects
for (Store *currentStore in self.twentyClosestStores) {
//Start monitoring "region"(CLCircularRegion)
[self.locationManager startMonitoringForRegion:currentStore.circularRegion];
}
}
//Stop monitoring "previousTwentyStores"(NSMutableArray) (20 closest stores before user's location updated)
-(void)stopMonitoringStores
{
//Run on all "monitoredRegions"(NSSet) of "locationManager"(CLLocationManager) objects
for (CLCircularRegion *currentRegion in self.locationManager.monitoredRegions) {
//Stop monitoring "region"(CLCircularRegion)
[self.locationManager stopMonitoringForRegion:currentRegion];
}
}
//Finding a store for region
-(Store*)storeForRegionCLCircularRegion*)region
{
//Run on all "allStores"(NSMutableArray)'s objects
for (Store *currentStore in self.allStores) {
//If "currentStore"(Store)'s "circularRegion"'s identifier is equal to "region"(CLCircularRegion)'s identifier
if ([currentStore.circularRegion.identifier isEqualToString:region.identifier]) {
//Returning "currentStore"(Store)
return currentStore;
}
}
//Store not found - returning nil
NSLog(@"No store found for this region: %f,%f",region.center.latitude,region.center.longitude);
return nil;
}
AppDelegate.m:
-(BOOL)applicationUIApplication *)application willFinishLaunchingWithOptionsNSDictionary *)launchOptions
{
self.monitorLocationVC=[[monitorLocationViewController alloc] init];
self.monitorLocationVC.locationManager=self.locationManager;
[self configureLocationManager];
[self.locationManager startUpdatingLocation];
return YES;
}
-(void)configureLocationManager
{
//Initializing locationManager
self.locationManager=[[CLLocationManager alloc] init];
//setting "locationManager"'s(CLLocationManager) delegate to "self"
self.locationManager.delegate=self.monitorLocationVC;
//Setting "locationManager"'s(CLLocationManager)'s distance filter to none
self.locationManager.distanceFilter=kCLDistanceFilterNone;
//Setting "locationManager"'s(CLLocationManager)'s activityType to navigation
self.locationManager.activityType=CLActivityTypeAutomotiveNavigation;
//setting "locationManager"'s(CLLocationManager) desiredAccuracy to "best"
self.locationManager.desiredAccuracy=kCLLocationAccuracyBestForNavigation;
self.locationManager.pausesLocationUpdatesAutomatically=NO;
//If OS version is 9 or above - setting "allowsBackgroundLocationUpdates" to YES
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
}
谢谢!
Best Answer-推荐答案 strong>
您只想监控区域,而不是在后台不断更新它们的位置。
试试这个:
self.locationManager.desiredAccuracy=kCLLocationAccuracyBest;
你真的需要将 distanceFilter 设置为 kCLDistanceFilterNone 吗?这将导致使用更多的电池电量。您可能想尝试将其设置为 10、20、50 甚至 100 米左右。
另外,为了不经常更新位置,而不是:
[self.locationManager startUpdatingLocation];
尝试使用:
[self.locationManager startMonitoringSignificantLocationChanges];
所有这些都应该有助于减少电池使用量。当您将精度和距离过滤器设置为尽可能高的设置时,电池将会耗尽。
编辑:
由于您的应用程序的目的,无论您做什么,都会消耗大量电池。我之前针对类似问题所做的一个解决方案是使用 NSTimer 创建算法或公式,该 NSTimer 每 x 分钟触发一次以更新用户的位置。 (但仅在区域移动 x 米时才更新区域)。
- 在 NSTimer 触发之间停止位置更新,这样您就不会不断更新位置。
- 当计时器触发时,恢复位置更新,抓取大约 10 个位置(这样您就可以获得准确的位置),然后关闭位置更新,直到下次触发计时器时
关于ios - 区域监控(地理围栏)会消耗电池电量(iOS),我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/35208989/
|