【问题标题】:iOS Geofencing with CoreLocation带有 CoreLocation 的 iOS 地理围栏
【发布时间】:2017-02-14 10:36:25
【问题描述】:

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

为此,我成功地在我的代码中知道用户是否在 100m 左右(使用CLRegionStateInside)。 DidEnterRegionDidExitRegion 也可以正常工作。我正在使用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


【解决方案1】:

关于后台监控的问题,请参考Apples文档,其中说明如下:

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

这意味着,只要您的 authorizationStatus 设置为 .authorizedAlways ,其余部分将自动处理。

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

【讨论】:

    猜你喜欢
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-25
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 2017-04-20
    • 1970-01-01
    相关资源
    最近更新 更多