Удаление уведомлений на основе местоположения, когда пользователь выходит из региона

Я установил (по умолчанию 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!"

Кто-нибудь пробовал что-то подобное? Документация неясно, как это можно сделать.

Ответ 1

CLRegion объект имеет специальные свойства для этого: notifyOnEntry и notifyOnExit.
Все, что вам нужно, - это обновить код следующим образом:

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
Присвоение значения этому свойство заставляет локальное уведомление доставляться, когда пользователь пересекает границу регионов. Сам объект области определяет инициируется ли уведомление при входе пользователя или выходе из него регион.

Ответ 2

Я действительно устал вчера и не смог завершить свой ответ вовремя.

Основываясь на некоторых ответах, у меня есть только ключ к тому, что вы должны делать. Я не пробовал это сам (геообработка - это действительно боль, чтобы проверить, я знаю это, потому что я работаю над проектом geofencing atm.), Мне также никогда не приходилось удалять отправленное уведомление из Центра уведомлений раньше.

Я предполагаю, что ваше приложение не завершится из-за всего процесса. Поэтому мы не будем использовать здесь функцию 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 */
    }
}

Это какая-то псевдомеханика, которую я бы построил, если бы мне пришлось, поэтому, если что-то не так или неправильно, я был бы признателен за ваши отзывы.:)

Ответ 3

Это очистит все уведомления приложений из Центра уведомлений.

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

Ответ 4

Похоже, вы можете очистить конкретное уведомление, если удерживаете объект UILocalNotification. Используя свой объект уведомления, который вы создали в приведенном выше примере, вы можете позвонить

[[UIApplication sharedApplication] cancelLocalNotification:notification];

чтобы очистить уведомление.

Ответ 5

Это похоже на очень простое решение. выполните следующие шаги, которые вам помогут.

  • Сделайте одно фоновое обслуживание, которое будет работать в фоновом режиме, чтобы проверить ваше местоположение.
  • Когда вы входите в местное уведомление о локальном пожаре, которое уже сделано вами. хорошая работа.
  • Но когда вы покидаете этот регион (проверьте справочную службу с указанием данных о местоположении, например, теперь местоположение совпадает с данными о местоположении, когда пользователь вводил этот регион). запустите новое локальное уведомление с пустыми данными. и он также очистит уведомление из окна уведомления.

Ответ 6

Вы должны вызвать фоновый метод, который должен вызываться только тогда, когда устройство выходит из местоположения. Это может быть достигнуто путем создания слоя для области и запуска сразу, когда он выходит из границы.

В этом методе вы можете либо удалить все уведомления о соответствующем приложении с помощью

[[UIApplication sharedApplication] cancelLocalNotification:notification];

или может удалить только определенное уведомление, вызвав

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

Вы получите все действующие уведомления, доступные для конкретного приложения. Удалите конкретное уведомление для определенного региона.

Ответ 7

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