当用户退出区域时,删除触发的基于位置的通知

时间:2015-07-27 07:06:04

标签: ios objective-c geolocation cllocationmanager

我为我的应用设置了基于位置的通知(默认iOS8)。

UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.regionTriggersOnce = NO;
notification.userInfo = @{ @"notification_id" : @"someID" };
notification.region = region;
notification.alertBody = alertBody;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];

当用户进入指定区域时,通知会正确显示在NotificationCenter中。

但是,我希望在用户退出该区域时删除该通知消息,因为用户回家并查看通知中心直到他们收到类似的消息是没有意义的:

  

"您在XXXXX!"

有没有人尝试过类似的东西?文档不清楚如何做到这一点。

7 个答案:

答案 0 :(得分:3)

CLRegion对象具有以下特殊属性:notifyOnEntrynotifyOnExit 您需要的一切都是以这种方式更新代码:

CLRegion *region = .... // Configure region here
region.notifyOnEntry = YES;
region.notifyOnExit = NO;  

UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.regionTriggersOnce = NO;
notification.userInfo = @{ @"notification_id" : @"someID" };
notification.region = region;
notification.alertBody = alertBody;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];

以下是解释它的Apple documentation

  

@property(nonatomic, copy) CLRegion *region
  为此分配值   属性导致在用户时传递本地通知   穿过该地区的边界   区域对象本身定义   用户进入或退出时是否触发通知   该地区。

答案 1 :(得分:1)

我昨天真的很累,无法及时完成答案。

根据这里的一些答案,我只知道你必须做什么。我自己没有尝试过(地理围栏是一个非常痛苦的测试,我知道因为我正在进行地理围栏项目工作。),我也从来没有必要删除通知中心发送的通知。 / p>

我认为您的申请不会因整个过程而终止。所以我们在这里不会使用startMonitoringForRegion函数。

用Swift 2.0编写的答案(将其翻译成ObjC并不难。)

func createAndRegisterSomeNotificationSomewhere() {

    let region = CLCircularRegion(center: someCoordinates, radius: someRadius, identifier: someIdentifier)

    region.notifyOnEntry = true
    region.notifyOnExit = true

    let locationNotification = UILocalNotification()
    locationNotification.alertBody = "someAlertBody"
    locationNotification.userInfo = ["notification_id" : "someID"]
    locationNotification.regionTriggersOnce = false
    locationNotification.region = region // remember 'presentLocalNotificationNow' will not work if this value is set

    UIApplication.sharedApplication().scheduleLocalNotification(locationNotification)
}

/* CLLocationManagerDelegate provides two function */

// func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion)
// func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion)

/* If I'm not mistaken they are only called for monitored regions and not location based local notifications */
/* I mean you will have to use something like: self.locationManager.startMonitoringForRegion(someCircularRegion) */
/* Correct me if I'm wrong. So consider to rebuild the following logic to ease everything if you want to monitor regions. */

/* Now when you receive your location notification */
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {

    if let region = notification.region {

        self.locationManager.requestStateForRegion(region)

        /* based on other answers this will remove your noticaiton from NC and cancel from showing it anywhere */
        application.cancelLocalNotification(notification)
        /* but we need this notification still be scheduled because 'region.notifyOnExit = true' should fire it again later */
        application.scheduleLocalNotification(notification)
    }
}

func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) {

    /* this is not the best solution, because it adds some latency to the dilivery code and CLRegionState can also be Unknown sometimes */
    /* I'd go with the two functions above if I only had up to 20 regions to monitor (max region limit per App, read CLLocationManager docs) */
    /* the mechanics would be more clear and save */

    switch state {

    case .Inside:

        /* create a new noticiation with the same cpecs as the cancled notification but this time withot the region */
        let sameNotificationAsAbove = UILocalNotification()
        /* if you really need to know your IDs inside userInfo so create some good mechanics to pass these before canceling */
        /* at least I would save the identifier of the region iside the noticiation */
        /* save the notification somewhere to delete it later from NC */
        self.someArrayToSaveDeliveredNotifications.append(sameNotificationAsAbove)

        /* fire the notification */
        UIApplication.sharedApplication().presentLocalNotificationNow(sameNotificationAsAbove)

    case default:

        /* if it is true that notication inside NC can be deleted just by calling 'cancelLocalNotification' function */
        /* so find your notification inside someArrayToSaveDeliveredNotifications bases on the region.identier which you saved inside userInfo */
        let notificationToCancel = self.getNotificationForIdentifier(region.identifier)

        UIApplication.sharedApplication().cancelLocalNotification(notificationToCancel)
        /* this should delete your notification from NC based on other answers */
    }
}

这是我必须建立的某种伪机制,所以如果有什么不对或不正确我会很高兴听到你的反馈。 :)

答案 2 :(得分:0)

这将清除来自通知中心的所有应用通知。

[[UIApplication sharedApplication] setApplicationIconBadgeNumber: 0];
[[UIApplication sharedApplication] cancelAllLocalNotifications];

答案 3 :(得分:0)

如果您按住UILocalNotification对象,似乎可以清除特定通知。使用您在上面的示例中创建的通知对象,您可以调用

[[UIApplication sharedApplication] cancelLocalNotification:notification];

清除通知。

答案 4 :(得分:0)

看起来非常简单的解决方案。按照以下步骤,它将帮助您。

  • 制作一个可在后台继续使用的后台服务,以检查您的位置。
  • 当您进入某个地区时,请点击您已完成的本地通知。干得好。
  • 但是当您离开该区域时(检查后台服务,输入位置详细信息,例如现在位置与用户在该区域中输入时的位置详细信息匹配)。使用空数据触发新的本地通知。而且它也将清除通知窗口中的通知。

答案 5 :(得分:0)

您应该触发一个后台方法,该方法只应在设备离开该位置时调用。这可以通过为区域创建图层并在其离开边界时立即触发来实现。

在该方法中,您可以通过

清除相应应用的所有通知
[[UIApplication sharedApplication] cancelLocalNotification:notification];

或者可以通过致电

清除特定通知
UIApplication* application = [UIApplication sharedApplication];
NSArray* scheduledNotifications = [NSArray arrayWithArray:application.scheduledLocalNotifications];
application.scheduledLocalNotifications = scheduledNotifications;

您将收到特定应用的所有有效通知。删除特定区域的特定通知。

答案 6 :(得分:0)

CLLocationManagerDelegate 委托有一组基于设备位置触发的方法。如;

-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region

在您的情况下,您需要做的是触发以下回调时;

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region

从NotificationCenter中删除您的通知