Pergunta

I have some code in my Mac app that performs a long-running export operation. At the end of the export, it creates a user notification to let the user know it's finished:

- (NSUserNotification*)deliverNotificationWithSound:(NSString*)sound title:(NSString*)title messageFormat:(NSString*)message {
    NSUserNotification * note = [NSUserNotification new];

    note.soundName = sound;
    note.title = title;
    note.informativeText = [NSString stringWithFormat:message, NSRunningApplication.currentApplication.localizedName, self.document.displayName];
    note.userInfo = @{ @"documentFileURL": self.document.fileURL.absoluteString };

    [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:note];
    return note;
}

It then puts a sheet up with details about the export (warnings encountered, a handy "Reveal" button, etc.). When they dismiss the sheet, I want to remove the notification, like so:

[NSUserNotificationCenter.defaultUserNotificationCenter removeDeliveredNotification:note];

However, this doesn't actually remove the notification from Notification Center. I've set a breakpoint; the -removeDeliveredNotification: line is run, and note is not nil. What gives?

Foi útil?

Solução

The notification you are attempting to be removed must be in the deliveredNotifications array. Quote the docs for -removeDeliveredNotification:

If the user notification is not in deliveredNotifications, nothing happens.

Your notification may be copied when you call -deliverNotification:, so keeping a reference to that instance and attempting to remove later it may fail. Instead, stash something in the notification's userInfo property so you can identify it, and scan through the deliveredNotifications array to find the notification you want to remove.


Added by Brent

Here's the corrected version of the method in my question. I'm using the original notification's pointer value, casted to an integer, to identify the copy; this isn't foolproof, but it's probably good enough.

- (NSUserNotification*)deliverNotificationWithSound:(NSString*)sound title:(NSString*)title messageFormat:(NSString*)message {
    NSUserNotification * note = [NSUserNotification new];

    note.soundName = sound;
    note.title = title;
    note.informativeText = [NSString stringWithFormat:message, NSRunningApplication.currentApplication.localizedName, self.document.displayName];
    note.userInfo = @{ @"documentFileURL": self.document.fileURL.absoluteString, @"originalPointer": @((NSUInteger)note) };

    [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:note];

    // NSUserNotificationCenter actually delivers a copy of the notification, not the original.
    // If we want to remove the notification later, we'll need that copy.
    for(NSUserNotification * deliveredNote in NSUserNotificationCenter.defaultUserNotificationCenter.deliveredNotifications) {
        if([deliveredNote.userInfo[@"originalPointer"] isEqualToNumber:note.userInfo[@"originalPointer"]]) {
            return deliveredNote;
        }
    }

    return nil;
}

Outras dicas

Thanks for the great question.

It seems like Apple was fixed issue because it will work for me by using the single line of code.

UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: aryIdentifier)

I have tried 5-6 hours in the simulator to clear local notification but no luck. When I will run code in the actual device it will like the charm.

Happy coding.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top