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

我为我的应用程序设置了(默认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正确显示在NotificationCenter

但是,我想在用户退出该区域时删除该通知消息,因为用户无法回家查看通知中心,直到他们收到如下所示的消息:

“你在XXXXX!”

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

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]; 

这里是苹果的文档解释它:

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

我昨天真的很累,不能及时完成答案。

基于这里的一些答案,我只知道你必须做什么。 我自己没有尝试过(geofencingtesting真的很痛苦,我知道因为我正在做一个geofencing项目atm),所以我也从来没有必要从Notification Center中删除已经发送的通知。

我假设你的申请不会由于整个过程而终止。 所以我们不会在这里使用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 */ } } 

如果我不得不这样做的话,这是一种假的机制,所以如果有什么错误或不正确的话,我会很乐意听到你的反馈。 🙂

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

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

看起来,如果持有UILocalNotification对象,则可以清除特定的通知。 使用您在上例中创build的通知对象,您可以调用

 [[UIApplication sharedApplication] cancelLocalNotification:notification]; 

清除通知。

这看起来非常简单的解决scheme。 按照下面的步骤,它会帮助你。

  • 使一个后台服务将继续在后台检查您的位置。
  • 当你进入某个地区时,你已经完成了本地通知。 好工作。
  • 但是,当你离开那个地区(检查后台服务与input位置的详细信息,如现在位置与用户input该地区时的位置详细信息匹配)。 用空数据激发新的本地通知。 而且还会从通知窗口中清除通知。

你应该触发一个只能在设备离开位置时调用的背景方法。 这可以通过为区域创build层并在触发边界时立即触发来实现。

在该方法中,您可以通过清除各个应用程序的所有通知

 [[UIApplication sharedApplication] cancelLocalNotification:notification]; 

或者可以通过调用只清除特定的通知

 UIApplication* application = [UIApplication sharedApplication]; NSArray* scheduledNotifications = [NSArray arrayWithArray:application.scheduledLocalNotifications]; application.scheduledLocalNotifications = scheduledNotifications; 

您将收到针对特定应用的所有有效通知。 删除特定地区的具体通知。

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 

在你的情况下,你必须做的是当下面的callback被触发;

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

从通知中心删除您的通知