【发布时间】:2017-02-14 10:36:25
【问题描述】:
我想知道用户何时在我家附近。 我正在使用 CoreLocation,并且希望始终知道用户是否在我家附近(大约 100m),即使应用程序已关闭。
为此,我成功地在我的代码中知道用户是否在 100m 左右(使用CLRegionStateInside)。 DidEnterRegion 和 DidExitRegion 也可以正常工作。我正在使用kCLAuthorizationStatusAuthorizedAlways 来本地化用户。
我想节省电池寿命,所以我添加了self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers; 以在用户行驶 3 公里后更新位置。
告诉我如何才能延长电池寿命,以及如何在应用处于后台/关闭状态时更新位置(也许我必须更改 AppDelegate 中的某些内容)?
我想知道我的代码是否能满足我的需求?
这是我的代码:
#import "ViewController.h"
@import UserNotifications;
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Request Notification
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!error) {
NSLog(@"request authorization succeeded!");
}
}];
}
- (void)setUpGeofences {
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(49.451096,
1.095425);
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center
radius:100.0
identifier:@"Home"];
[self.locationManager startMonitoringForRegion:region];
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
self.locationManager.allowsBackgroundLocationUpdates = YES;
}
- (void)showSorryAlert {
UIAlertController *alert = [UIAlertController
alertControllerWithTitle:@"Info"
message:@"You are using UIAlertController"
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
switch (status) {
case kCLAuthorizationStatusNotDetermined:
[self.locationManager requestAlwaysAuthorization];
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
[self.locationManager startUpdatingLocation];
[self setUpGeofences];
break;
case kCLAuthorizationStatusAuthorizedAlways:
[self.locationManager startUpdatingLocation];
[self setUpGeofences];
break;
case kCLAuthorizationStatusRestricted:
// restricted by e.g. parental controls. User can't enable Location Services
break;
case kCLAuthorizationStatusDenied:
// user denied your app access to Location Services, but can grant access from Settings.app
break;
default:
break;
}
}
- (void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region {
NSLog(@"didEnter : %@", region);
[self displayNotif:@"Bienvenue !" withBody:@"Passez nous voir !"];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
[self displayNotif:@"Au revoir !" withBody:@"A bientôt !"];
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
NSLog(@"Start monitoring for region: %@", region.identifier);
[self.locationManager requestStateForRegion:region];
}
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
NSLog(@"Error: %@", error);
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
NSLog(@"NEW LOCATION");
// Stop location updates when they aren't needed anymore
[self.locationManager stopUpdatingLocation];
// Disable background location updates when they aren't needed anymore
self.locationManager.allowsBackgroundLocationUpdates = NO;
}
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
// When regions are initialized, see if we are already within the geofence.
switch (state) {
case CLRegionStateInside: [self displayNotif:@"Bienvenue" withBody:@"Passez nous voir !"];
break;
case CLRegionStateUnknown: NSLog(@"Unknown");
case CLRegionStateOutside: NSLog(@"Outside");
default: break;
}
}
- (void)displayNotif:(NSString *)title withBody:(NSString *)body {
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:body
arguments:nil];
content.sound = [UNNotificationSound defaultSound];
/// 4. update application icon badge number
content.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
// Deliver the notification in five seconds.
UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:1.f repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"OneSecond"
content:content trigger:trigger];
/// 3. schedule localNotification
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(@"add NotificationRequest succeeded!");
}
}];
}
@end
【问题讨论】:
-
如果您使用的是 CLCircularRegion,则无需开始位置更新或设置所需的精度、距离过滤器等。只需添加区域并开始监控它。而已。 iOS 将负责监控用户位置并在需要时调用您的区域委托方法
标签: ios objective-c core-location cllocationmanager geofencing