使用CoreLocation进行iOS Geofencing

时间:2016-10-05 20:33:28

标签: ios objective-c core-location cllocationmanager geofencing

我想知道用户何时在我家附近。 我正在使用CoreLocation,并希望始终知道用户是否在我家附近(大约100米),即使该应用已关闭。

为此,我成功地在我的代码中知道用户是否在100米左右(CLRegionStateInside)。 DidEnterRegionDidExitRegion也可以。我使用kCLAuthorizationStatusAuthorizedAlways来本地化用户。

我想节省电池寿命,所以我在用户制作3公里后添加了self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;来更新位置。

告诉我如何才能节省更多的电池续航时间,即使应用程序处于后台/关闭状态(也许我还要更改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

1 个答案:

答案 0 :(得分:1)

关于您在后台进行监控的问题,请参阅Apples文档,其中说明了以下内容:

  

如果在应用未运行时越过区域边界,则会将该应用重新启动到后台以处理该事件。同样,如果应用程序在事件发生时被暂停,它会被唤醒,并且会花费很短的时间(大约10秒)来处理事件。

这意味着,只要您的authorizationStatus被设置为.AdentifiedAlways那么剩下的就会自动处理它。

链接到其他文档:https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html#//apple_ref/doc/uid/TP40009497-CH9-SW1