如何在iOS上使用基于地理位置的推送通知?

don*_*ias 24 iphone geolocation push-notification apple-push-notifications ios

当应用程序被杀死时(不在后台),是否可以在iOS上使用基于地理位置的推送通知?

我有兴趣构建一个应用程序,用户将在地图上选择一个位置,然后如果他/她接近该区域,则会触发本地基于地理位置的推送通知.

然而这个"想法"是否可能?当应用程序被杀死并运行时,GPS可以运行并比较坐标,并在适当的时候通知用户吗?是否有关于这个主题的教程/文章/更多信息我可以阅读?

我在网上看到的大多数信息更像是在没有任何具体内容的情况下实施的一般想法.

gav*_*net 34

为了在应用程序未运行时跟踪用户的位置(即之前已被终止),有两种选择:

  1. 从"跟踪用户位置"下的iOS应用程序编程指南:

    对于不需要高精度位置数据的应用,强烈建议使用重要更改位置服务.使用此服务,仅当用户的位置发生显着变化时才会生成位置更新; 因此,它非常适合为用户提供非关键的,与位置相关的信息的社交应用或应用.如果在更新发生时暂停应用程序,系统会在后台将其唤醒以处理更新.如果应用程序启动此服务然后终止,系统会在新位置可用时自动重新启动应用程序.此服务在iOS 4及更高版本中可用,并且仅在包含蜂窝无线电的设备上可用.

    但是,根据CLLocationManager类引用,它不太准确,并且更新很少:

    注意:只要设备从之前的通知移动500米或更长时间,应用就会收到通知.它不应该比每五分钟更频繁地预期通知.如果设备能够从网络检索数据,则位置管理器更有可能及时发送通知.

  2. 区域监控以类似的方式工作 - 包括终止后重新启动应用程序 - 但具有更高的准确性(取决于Wifi网络和手机信号塔的可用性):

    特定阈值距离由当前可用的硬件和定位技术确定.例如,如果禁用Wi-Fi,则区域监控的准确性要低得多.但是,出于测试目的,您可以假设最小距离约为200米.

    另一个区域监视考虑因素是(根据CLLocationManager类引用)区域入口和出口通知可能仅在跨越区域边界后3-5分钟左右收到.

    根据实际要求,区域监测可用于获得"粗略"位置,然后当用户在特定区域内时,在位置管理器上启动更准确的基于GPS的服务.当用户离开感兴趣的区域时,关闭GPS服务以保留电池并再次恢复到粗略位置监视服务(即区域监视).这是一个基本的实现:

    SomeViewController.m:

    ...
    @interface SomeViewController () <CLLocationManagerDelegate>
    
    @property (nonatomic, strong) CLLocationManager *locationManager;
    @property (nonatomic, strong) CLRegion *someRegion;
    
    @end
    
    @implementation SomeViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        self.locationManager = [[CLLocationManager alloc] init];
    
        CLLocationDistance radius = 10; // 10 metre sensitivity
        self.someRegion = [[CLRegion alloc] initCircularRegionWithCenter:someCoordinates radius:radius identifier:@"Smithtown Dry Cleaners"];
    
        self.locationManager.delegate = self;
        [self.locationManager startMonitoringForRegion:self.someRegion];
    
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        self.locationManager.distanceFilter = 10;
        [self.locationManager startUpdatingLocation];
    }
    
    - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
    {
        [self.locationManager startUpdatingLocation];
    }
    
    - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
    {
        [self.locationManager stopUpdatingLocation];
    }
    
    // Delegate method from the CLLocationManagerDelegate protocol.
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
        CLLocation* location = [locations lastObject];
    
        // If the user's current location is not within the region anymore, stop updating
        if ([self.someRegion containsCoordinate:location.coordinate] == NO) {
            [self.locationManager stopUpdatingLocation];
        }
    
        NSString *locationData = [NSString stringWithFormat:@"latitude %+.6f, longitude %+.6f\n",
                                  location.coordinate.latitude,
                                  location.coordinate.longitude];
        NSLog(@"%@", locationData);
    
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.alertBody = locationData;
        localNotification.alertAction = @"Location data received";
        localNotification.hasAction = YES;
        [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    请记住将相应的条目添加到应用程序的plist文件中,以便应用程序在后台运行并访问相应的资源:

    MyApp-Info.plist:

    <key>UIBackgroundModes</key>
    <array>
            ...
            <string>location</string>
    </array>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
            ...
            <string>location-services</string>
            <string>gps</string>
    </array>
    
    Run Code Online (Sandbox Code Playgroud)

    上面的代码假定使用iOS6和ARC