2013-05-09 18 views
6

Wydaje się, żewykryć niepotwierdzone UILocalNotifications

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

i

didReceiveLocalNotification:(UILocalNotification *)notification

są uruchamiane tylko wtedy, gdy użytkownik potwierdza UILocalNotification, na przykład przesuwając suwak lub dotykając wpis w iOS Powiadomienie rozwijane.

Czy jest jakiś sposób, aby stwierdzić, że zgłoszenie UILocalNotification zostało przerwane, jeśli użytkownik zignoruje zgłoszenie UILocalNotification i ponownie włączy aplikację przez kliknięcie ikony aplikacji?

Powinienem wspomnieć, że tak naprawdę dotyczy to tylko powtarzania powiadomień, ponieważ wystrzelenie nie powtarzających się powiadomień można wykryć, obserwując całkowitą liczbę. To znaczy, kiedy wystrzeliwują, znikają z [[UIApplication sharedApplication] scheduledLocalNotifications].

szukam czegoś jak ..

[[UIApplication sharedApplication] unacknowledgedLocalNotifications]

Niestety, nie mogę znaleźć czegoś podobnego.

+0

Jeżeli zgłoszenie jest * nie * w 'scheduleLocalNotifications', nie jest już zaplanowany, więc musiał zostać uruchomiony. – matt

+0

"właśnie zredagowałem pytanie. Faktycznie miałem tam ten tekst, ale chciałem, aby rzeczy były tak proste, jak tylko mogłem (tj. Mniej tekstu). –

+3

Mam wrażenie, że to, czego chcesz, nie istnieje, ale spowodowałoby to * wspaniałe * żądanie funkcji z Apple Reporterem błędów. – matt

Odpowiedz

5

Możesz sprawdzić zaplanowane powiadomienia pod numerem [[UIApplication sharedApplication] scheduledLocalNotifications]. Aby sprawdzić, czy zaplanowane powtarzające się powiadomienie zostało uruchomione, należy uzyskać dostęp do właściwości fireDate, aby sprawdzić, jaka była początkowa data powiadomienia. Następnie sprawdź właściwość repeatInterval.

Więc masz dwie zmienne, jedna to początkowa NSDate, powiedzmy 2013-05-08 12:00, a druga to interwał powtarzania, powiedzmy codziennie. I robiąc [NSDate date] otrzymasz aktualną datę, w której znajduję się (w Szwecji), teraz jest 2013-05-09 22:45. Oznacza to, że istnieje jedno powiadomienie, na które użytkownik nie zareagował.

Musisz więc utworzyć metodę, która pobierze te argumenty, a następnie rozpocznie iterację od daty początkowej, aby zobaczyć, ile powiadomień zostało pominiętych do bieżącej daty.

Użyteczne jest NSCalendar s dateByAddingComponents:toDate:options.

+0

Prawdę powiedziawszy, byłem w trakcie wdrażania tego i myślałem, że Apple _had_ to załatwił, aby uratować mi kilka linii. Dzięki! –

+0

Ja też, niestety, musisz to zaimplementować samodzielnie. To trochę pracy, ale ładnie działa. –

+0

Każdy powód, dla którego używasz NSCalendars i Components, a nie po prostu NSDate's timeIntervalSinceNow? Abyś mógł coś takiego jak 'for (UILocalNotification * uiln w [[UIApplication sharedApplication] scheduleLocalNotifications]) {if ([uiln.fireDate timeIntervalSinceNow] <0) // wykonaj pewne rzeczy}' –

2

Wszyscy prawdopodobnie pojawili się, ale chciałbym podzielić się moim rozwiązaniem tego problemu. (Przepraszam za długie nazwy zmiennych ...)

Pomysł jest prosty: zawsze przechowuj fireDate w przyszłości.

-Co didFinishLaunchingWithOptions czasowych lub didReceiveLocalNotification wywoływana jest po prostu anulować bieżące powiadomienia i przełożyć nowy z fireDate jedną jednostkę interwału w przyszłości

-Gdy Twoje uruchamia app iterację wszystkich zaplanowanych zgłoszeń, jeżeli fireDate nie jest w przyszłości, wiesz, że zostało zignorowane:

W moim przypadku powiadomienia mają cotygodniowy okres powtarzania.I najpierw przełożyć żadnych potwierdzonych zgłoszeń didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    UILocalNotification* localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; 

    if (localNotif != nil) 
    { 
     [NotificationsHelper rescheduleNotification:localNotif]; 
    } 
} 

a także w didReceiveLocalNotification:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *) notification 
{ 
    [NotificationsHelper rescheduleNotification:notification]; 
} 

podczas uruchamiania aplikacji sprawdzić wszystkie powiadomienia dla któregokolwiek z fireDate w przeszłości:

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    [self checkLocalNotifications:application]; 
} 

Kod mojej funkcji "checkLocalNotifications":

- (void) checkLocalNotifications:(UIApplication *) application 
{ 
    UIApplication* app  = [UIApplication sharedApplication]; 
    NSArray*  eventArray = [app scheduledLocalNotifications]; 

    for (int i = 0; i < [eventArray count]; i++) 
    { 
     UILocalNotification* notification = [eventArray objectAtIndex:i]; 

     if ([NotificationsHelper wasWeeklyRepeatingNotificationIgnored:notification]) 
     { 
      [NotificationsHelper rescheduleNotification:notification]; 

      NSLog(@"NotificationWasIgnored: %@ %@",notification.alertAction, notification.alertBody); 
     } 
    } 
} 

Kod dla mojej funkcji "wasWeeklyRepeatingNotificationIgnored":

+ (BOOL) wasWeeklyRepeatingNotificationIgnored:(UILocalNotification*) the_notification 
{ 
    BOOL result; 
    NSDate* now = [NSDate date]; 

    // FireDate is earlier than now 
    if ([the_notification.fireDate compare:now] == NSOrderedAscending) 
    { 
     result = TRUE; 
    } 
    else 
    { 
     result = FALSE; 
    } 

    return result; 
} 

Kod dla mojej funkcji "rescheduleNotification":

+ (void) rescheduleNotification:(UILocalNotification*) the_notification 
{ 
    UILocalNotification* new_notification = [[UILocalNotification alloc] init]; 

    NSMutableDictionary* userinfo = [[NSMutableDictionary alloc] init]; 

    [new_notification setUserInfo:userinfo]; 
    [new_notification setRepeatInterval:the_notification.repeatInterval]; 
    [new_notification setSoundName:UILocalNotificationDefaultSoundName]; 
    [new_notification setTimeZone:[NSTimeZone defaultTimeZone]]; 
    [new_notification setAlertAction:the_notification.alertAction]; 
    [new_notification setAlertBody:the_notification.alertBody]; 
    [new_notification setRepeatCalendar:[NSCalendar currentCalendar]]; 
    [new_notification setApplicationIconBadgeNumber:the_notification.applicationIconBadgeNumber]; 

    NSCalendar*  gregorian   = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    NSDateComponents* weekdayComponents = [gregorian components:NSWeekdayCalendarUnit 
                 fromDate:the_notification.fireDate]; 

    NSInteger weekday = [weekdayComponents weekday]; 
    NSDate* next_week = [self addDay:weekday toHourMinute:the_notification.fireDate]; 

    [new_notification setFireDate:next_week]; 

    [[UIApplication sharedApplication] scheduleLocalNotification:new_notification]; 
    [[UIApplication sharedApplication] cancelLocalNotification:the_notification]; 
} 
+0

Znowu będzie działać tylko z powtarzającymi się nazwami UILN, ponieważ w przeciwnym razie UILN nie będzie istnieć w systemie. Oznacza to, że iOS usuwa nieuchronne UILN, które uruchamiają się. –

+0

Nawiasem mówiąc, nigdy nie przepraszaj za długie nazwy zmiennych .. IMHO, lepiej będzie przesadzić, jak opisowe są twoje imiona. I niezły kod. –

0

Jeśli UILocalNotifications zwiększamy liczbę ikon aplikacji odznakę (tj liczba w czerwonym kółku na prawym górnym rogu aplikacji ikony), to istnieje śmiesznie prosty sposobem sprawdzenia niepotwierdzonych UILocalNotifications: po prostu sprawdzić, jaka jest obecna applicationIconBadgeNumber jest:

- (void)applicationWillEnterForeground:(UIApplication *)application 
{   
    int unacknowledgedNotifs = application.applicationIconBadgeNumber; 
    NSLog(@"I got %d unacknowledged notifications", unacknowledgedNotifs); 
    //do something about it... 

    //You might want to reset the count afterwards: 
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; 

} 
+0

Znaczek nie zmienia się, jeśli użytkownik odrzuci powiadomienie z zasobnika. – Maq

Powiązane problemy