1010#import " LeanplumInternal.h"
1111#import " LPNotificationsConstants.h"
1212#import " LPNotificationsManager.h"
13+ #import < UserNotifications/UNUserNotificationCenter.h>
1314
1415@implementation LPLocalNotificationsManager
1516
@@ -41,15 +42,9 @@ - (void)listenForLocalNotifications
4142 BOOL contentAvailable = [context boolNamed: @" iOS options.Preload content" ];
4243 NSString *message = [context stringNamed: @" Message" ];
4344
44- // Don't send notification if the user doesn't have the permission enabled.
45- if ([app respondsToSelector: @selector (currentUserNotificationSettings )]) {
46- BOOL isSilentNotification = message.length == 0 && contentAvailable;
47- if (!isSilentNotification) {
48- UIUserNotificationSettings *currentSettings = [app currentUserNotificationSettings ];
49- if ([currentSettings types ] == UIUserNotificationTypeNone) {
50- return NO ;
51- }
52- }
45+ if (![self shouldSendNotificationForMessage: message contentAvailable: contentAvailable])
46+ {
47+ return NO ;
5348 }
5449
5550 NSString *messageId = context.messageId ;
@@ -67,53 +62,17 @@ - (void)listenForLocalNotifications
6762 int countdownSeconds = [countdown intValue ];
6863 NSDate *eta = [[NSDate date ] dateByAddingTimeInterval: countdownSeconds];
6964
70- // If there's already one scheduled before the eta, discard this.
71- // Otherwise, discard the scheduled one.
72- NSArray *notifications = [app scheduledLocalNotifications ];
73- for (UILocalNotification *notification in notifications) {
74- NSString *messageId = [[LPNotificationsManager shared ] messageIdFromUserInfo: [notification userInfo ]];
75- if ([messageId isEqualToString: context.messageId]) {
76- NSComparisonResult comparison = [notification.fireDate compare: eta];
77- if (comparison == NSOrderedAscending) {
78- return NO ;
79- } else {
80- [app cancelLocalNotification: notification];
81- }
82- }
83- }
84-
85- UILocalNotification *localNotif = [[UILocalNotification alloc ] init ];
86- localNotif.fireDate = eta;
87- localNotif.timeZone = [NSTimeZone defaultTimeZone ];
88- if (message) {
89- localNotif.alertBody = message;
90- } else {
91- localNotif.alertBody = LP_VALUE_DEFAULT_PUSH_MESSAGE;
92- }
93- localNotif.alertAction = @" View" ;
94-
95- if ([localNotif respondsToSelector: @selector (setCategory: )]) {
96- NSString *category = [context stringNamed: @" iOS options.Category" ];
97- if (category) {
98- localNotif.category = category;
99- }
100- }
101-
102- NSString *sound = [context stringNamed: @" iOS options.Sound" ];
103- if (sound) {
104- localNotif.soundName = sound;
105- } else {
106- localNotif.soundName = UILocalNotificationDefaultSoundName;
107- }
108-
109- NSString *badge = [context stringNamed: @" iOS options.Badge" ];
110- if (badge) {
111- localNotif.applicationIconBadgeNumber = [badge intValue ];
65+ if ([self shouldDiscard: eta context: context])
66+ {
67+ return NO ;
11268 }
113-
69+
11470 NSDictionary *userInfo = [context dictionaryNamed: @" Advanced options.Data" ];
11571 NSString *openAction = [context stringNamed: LP_VALUE_DEFAULT_PUSH_ACTION];
11672 BOOL muteInsideApp = [context boolNamed: @" Advanced options.Mute inside app" ];
73+ NSString *sound = [context stringNamed: @" iOS options.Sound" ];
74+ NSString *badge = [context stringNamed: @" iOS options.Badge" ];
75+ NSString *category = [context stringNamed: @" iOS options.Category" ];
11776
11877 // Specify custom data for the notification
11978 NSMutableDictionary *mutableInfo;
@@ -140,11 +99,76 @@ - (void)listenForLocalNotifications
14099 mutableInfo[LP_KEY_PUSH_NO_ACTION] = messageId;
141100 }
142101 }
102+
103+ if (@available (iOS 10.0 , *)) {
104+ UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc ] init ];
105+
106+ if (message) {
107+ content.body = message;
108+ } else {
109+ content.body = LP_VALUE_DEFAULT_PUSH_MESSAGE;
110+ }
111+
112+ if (category) {
113+ content.categoryIdentifier = category;
114+ }
115+
116+ if (sound) {
117+ content.sound = [UNNotificationSound soundNamed: sound];
118+ } else {
119+ content.sound = [UNNotificationSound defaultSound ];
120+ }
143121
144- localNotif.userInfo = mutableInfo;
122+ if (badge) {
123+ content.badge = [NSNumber numberWithInt: [badge intValue ]];
124+ }
145125
146- // Schedule the notification
147- [app scheduleLocalNotification: localNotif];
126+ content.userInfo = mutableInfo;
127+
128+ NSDateComponents *dateComponenets = [[NSDateComponents alloc ] init ];
129+ [dateComponenets setSecond: countdownSeconds];
130+ UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents: dateComponenets repeats: NO ];
131+
132+ UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier: messageId content: content trigger: trigger];
133+
134+ [[UNUserNotificationCenter currentNotificationCenter ] addNotificationRequest: request withCompletionHandler: ^(NSError * _Nullable error) {
135+ if (error) {
136+ LPLog (LPError, error.localizedDescription );
137+ }
138+ }];
139+
140+ } else {
141+ UILocalNotification *localNotif = [[UILocalNotification alloc ] init ];
142+ localNotif.fireDate = eta;
143+ localNotif.timeZone = [NSTimeZone defaultTimeZone ];
144+ if (message) {
145+ localNotif.alertBody = message;
146+ } else {
147+ localNotif.alertBody = LP_VALUE_DEFAULT_PUSH_MESSAGE;
148+ }
149+ localNotif.alertAction = @" View" ;
150+
151+ if ([localNotif respondsToSelector: @selector (setCategory: )]) {
152+ if (category) {
153+ localNotif.category = category;
154+ }
155+ }
156+
157+ if (sound) {
158+ localNotif.soundName = sound;
159+ } else {
160+ localNotif.soundName = UILocalNotificationDefaultSoundName;
161+ }
162+
163+ if (badge) {
164+ localNotif.applicationIconBadgeNumber = [badge intValue ];
165+ }
166+
167+ localNotif.userInfo = mutableInfo;
168+
169+ // Schedule the notification
170+ [app scheduleLocalNotification: localNotif];
171+ }
148172
149173 if ([LPConstantsState sharedState ].isDevelopmentModeEnabled ) {
150174 LPLog (LPInfo, @" Scheduled notification" );
@@ -157,20 +181,102 @@ - (void)listenForLocalNotifications
157181 LP_END_USER_CODE
158182 UIApplication *app = [UIApplication sharedApplication ];
159183 NSArray *notifications = [app scheduledLocalNotifications ];
160- BOOL didCancel = NO ;
184+ if (@available (iOS 10.0 , *)) {
185+ __block BOOL didCancel = NO ;
186+ dispatch_semaphore_t semaphor = dispatch_semaphore_create (0 );
187+ [UNUserNotificationCenter .currentNotificationCenter getPendingNotificationRequestsWithCompletionHandler: ^(NSArray <UNNotificationRequest *> * _Nonnull requests) {
188+ for (UNNotificationRequest *request in requests) {
189+ NSString *messageId = [[LPNotificationsManager shared ] messageIdFromUserInfo: [request.content userInfo ]];
190+ if ([messageId isEqualToString: context.messageId]) {
191+ [UNUserNotificationCenter .currentNotificationCenter removeDeliveredNotificationsWithIdentifiers: @[request.identifier]];
192+ if ([LPConstantsState sharedState ].isDevelopmentModeEnabled ) {
193+ LPLog (LPInfo, @" Cancelled notification" );
194+ }
195+ didCancel = YES ;
196+ }
197+ }
198+ dispatch_semaphore_signal (semaphor);
199+ }];
200+ dispatch_time_t waitTime = dispatch_time (DISPATCH_TIME_NOW, 5.0 * NSEC_PER_SEC);
201+ dispatch_semaphore_wait (semaphor, waitTime);
202+ LP_BEGIN_USER_CODE
203+ return didCancel;
204+ } else {
205+ // Fallback on earlier versions
206+ BOOL didCancel = NO ;
207+ for (UILocalNotification *notification in notifications) {
208+ NSString *messageId = [[LPNotificationsManager shared ] messageIdFromUserInfo: [notification userInfo ]];
209+ if ([messageId isEqualToString: context.messageId]) {
210+ [app cancelLocalNotification: notification];
211+ if ([LPConstantsState sharedState ].isDevelopmentModeEnabled ) {
212+ LPLog (LPInfo, @" Cancelled notification" );
213+ }
214+ didCancel = YES ;
215+ }
216+ }
217+ LP_BEGIN_USER_CODE
218+ return didCancel;
219+ }
220+ }];
221+ }
222+
223+ - (BOOL )shouldSendNotificationForMessage : (NSString *)message contentAvailable : (BOOL )contentAvailable
224+ {
225+ // Don't send notification if the user doesn't have the permission enabled.
226+ if ([[UIApplication sharedApplication ] respondsToSelector: @selector (currentUserNotificationSettings )]) {
227+ BOOL isSilentNotification = message.length == 0 && contentAvailable;
228+ if (!isSilentNotification) {
229+ UIUserNotificationSettings *currentSettings = [[UIApplication sharedApplication ] currentUserNotificationSettings ];
230+ if ([currentSettings types ] == UIUserNotificationTypeNone) {
231+ return NO ;
232+ }
233+ }
234+ }
235+ return YES ;
236+ }
237+
238+ - (BOOL )shouldDiscard : (NSDate *)eta context : (LPActionContext *)context
239+ {
240+ // If there's already one scheduled before the eta, discard this.
241+ // Otherwise, discard the scheduled one.
242+ if (@available (iOS 10.0 , *)) {
243+ __block BOOL shouldDiscard = NO ;
244+ dispatch_semaphore_t semaphor = dispatch_semaphore_create (0 );
245+ [UNUserNotificationCenter .currentNotificationCenter getPendingNotificationRequestsWithCompletionHandler: ^(NSArray <UNNotificationRequest *> * _Nonnull requests) {
246+ for (UNNotificationRequest *request in requests) {
247+ NSString *messageId = [[LPNotificationsManager shared ] messageIdFromUserInfo: [request.content userInfo ]];
248+ if ([messageId isEqualToString: context.messageId]) {
249+ UNCalendarNotificationTrigger *trigger = (UNCalendarNotificationTrigger *)request.trigger ;
250+ NSComparisonResult comparison = [trigger.nextTriggerDate compare: eta];
251+ if (comparison == NSOrderedAscending) {
252+ shouldDiscard = YES ;
253+ break ;
254+ } else {
255+ [UNUserNotificationCenter .currentNotificationCenter removeDeliveredNotificationsWithIdentifiers: @[request.identifier]];
256+ }
257+ }
258+ }
259+ dispatch_semaphore_signal (semaphor);
260+ }];
261+ dispatch_time_t waitTime = dispatch_time (DISPATCH_TIME_NOW, 5.0 * NSEC_PER_SEC);
262+ dispatch_semaphore_wait (semaphor, waitTime);
263+ return shouldDiscard;
264+ } else {
265+ // Fallback on earlier versions
266+ NSArray *notifications = [[UIApplication sharedApplication ] scheduledLocalNotifications ];
161267 for (UILocalNotification *notification in notifications) {
162268 NSString *messageId = [[LPNotificationsManager shared ] messageIdFromUserInfo: [notification userInfo ]];
163269 if ([messageId isEqualToString: context.messageId]) {
164- [app cancelLocalNotification: notification];
165- if ([LPConstantsState sharedState ].isDevelopmentModeEnabled ) {
166- LPLog (LPInfo, @" Cancelled notification" );
270+ NSComparisonResult comparison = [notification.fireDate compare: eta];
271+ if (comparison == NSOrderedAscending) {
272+ return YES ;
273+ } else {
274+ [[UIApplication sharedApplication ] cancelLocalNotification: notification];
167275 }
168- didCancel = YES ;
169276 }
170277 }
171- LP_BEGIN_USER_CODE
172- return didCancel;
173- }];
278+ return NO ;
279+ }
174280}
175281
176282@end
0 commit comments