From 3e5360500949d264c115d6e7e176234e4c03f349 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Fri, 14 Apr 2017 15:27:31 -0400 Subject: [PATCH] Improve thread safety in PushManager and NotificationsManager. // FREEBIE --- Signal/src/environment/NotificationsManager.m | 38 ++++++++------- Signal/src/network/PushManager.m | 48 ++++++++++--------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/Signal/src/environment/NotificationsManager.m b/Signal/src/environment/NotificationsManager.m index ca16589a7..d8f6afa05 100644 --- a/Signal/src/environment/NotificationsManager.m +++ b/Signal/src/environment/NotificationsManager.m @@ -211,31 +211,33 @@ - (void)presentNotification:(UILocalNotification *)notification identifier:(NSString *)identifier { - AssertIsOnMainThread(); - - // Replace any existing notification - // e.g. when an "Incoming Call" notification gets replaced with a "Missed Call" notification. - if (self.currentNotifications[identifier]) { - [self cancelNotificationWithIdentifier:identifier]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + // Replace any existing notification + // e.g. when an "Incoming Call" notification gets replaced with a "Missed Call" notification. + if (self.currentNotifications[identifier]) { + [self cancelNotificationWithIdentifier:identifier]; + } - [[UIApplication sharedApplication] scheduleLocalNotification:notification]; - DDLogDebug(@"%@ presenting notification with identifier: %@", self.tag, identifier); + [[UIApplication sharedApplication] scheduleLocalNotification:notification]; + DDLogDebug(@"%@ presenting notification with identifier: %@", self.tag, identifier); - self.currentNotifications[identifier] = notification; + self.currentNotifications[identifier] = notification; + }); } - (void)cancelNotificationWithIdentifier:(NSString *)identifier { - AssertIsOnMainThread(); - UILocalNotification *notification = self.currentNotifications[identifier]; - if (!notification) { - DDLogWarn(@"%@ Couldn't cancel notification because none was found with identifier: %@", self.tag, identifier); - return; - } - [self.currentNotifications removeObjectForKey:identifier]; + dispatch_async(dispatch_get_main_queue(), ^{ + UILocalNotification *notification = self.currentNotifications[identifier]; + if (!notification) { + DDLogWarn( + @"%@ Couldn't cancel notification because none was found with identifier: %@", self.tag, identifier); + return; + } + [self.currentNotifications removeObjectForKey:identifier]; - [[UIApplication sharedApplication] cancelLocalNotification:notification]; + [[UIApplication sharedApplication] cancelLocalNotification:notification]; + }); } #pragma mark - Logging diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index c2cb95399..8a6ddc066 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -431,32 +431,34 @@ NSString *const PushManagerUserInfoKeysCallBackSignalRecipientId = @"PushManager - (void)presentNotification:(UILocalNotification *)notification checkForCancel:(BOOL)checkForCancel { - OWSAssert([NSThread isMainThread]); - - NSString *threadId = notification.userInfo[Signal_Thread_UserInfo_Key]; - if (checkForCancel && threadId != nil) { - // The longer we wait, the more obsolete notifications we can suppress - - // but the more lag we introduce to notification delivery. - const CGFloat kDelaySeconds = 0.3f; - notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:kDelaySeconds]; - notification.timeZone = [NSTimeZone localTimeZone]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *threadId = notification.userInfo[Signal_Thread_UserInfo_Key]; + if (checkForCancel && threadId != nil) { + // The longer we wait, the more obsolete notifications we can suppress - + // but the more lag we introduce to notification delivery. + const CGFloat kDelaySeconds = 0.3f; + notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:kDelaySeconds]; + notification.timeZone = [NSTimeZone localTimeZone]; + } - [[UIApplication sharedApplication] scheduleLocalNotification:notification]; - [self.currentNotifications addObject:notification]; + [[UIApplication sharedApplication] scheduleLocalNotification:notification]; + [self.currentNotifications addObject:notification]; + }); } -- (void)cancelNotificationsWithThreadId:(NSString *)threadId { - OWSAssert([NSThread isMainThread]); - - NSMutableArray *toDelete = [NSMutableArray array]; - [self.currentNotifications enumerateObjectsUsingBlock:^(UILocalNotification *notif, NSUInteger idx, BOOL *stop) { - if ([notif.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) { - [[UIApplication sharedApplication] cancelLocalNotification:notif]; - [toDelete addObject:notif]; - } - }]; - [self.currentNotifications removeObjectsInArray:toDelete]; +- (void)cancelNotificationsWithThreadId:(NSString *)threadId +{ + dispatch_async(dispatch_get_main_queue(), ^{ + NSMutableArray *toDelete = [NSMutableArray array]; + [self.currentNotifications + enumerateObjectsUsingBlock:^(UILocalNotification *notif, NSUInteger idx, BOOL *stop) { + if ([notif.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) { + [[UIApplication sharedApplication] cancelLocalNotification:notif]; + [toDelete addObject:notif]; + } + }]; + [self.currentNotifications removeObjectsInArray:toDelete]; + }); } + (NSString *)tag