Skip to content

Commit d945506

Browse files
Ryan Eberhardtreberhardt7
authored andcommitted
Use UserNotifications to create local notifications
a15e038 adds support for enumerating/dismissing delivered notifications by ID, but UserNotifications notifications and UILocalNotification notifications have a different set of IDs (a notification created using UILocalNotification will have an ID that does not match the notification's ID in the UserNotifications world and hence cannot be used to dismiss that notification). This commit creates the notifications using UserNotifications if the user is on iOS 10.
1 parent 6b7bb9c commit d945506

File tree

3 files changed

+84
-27
lines changed

3 files changed

+84
-27
lines changed

README.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,6 @@ Example:
326326
let localNotification = NotificationsIOS.localNotification({
327327
alertBody: "Local notificiation!",
328328
alertTitle: "Local Notification Title",
329-
alertAction: "Click here to open",
330329
soundName: "chime.aiff",
331330
category: "SOME_CATEGORY",
332331
userInfo: { }
@@ -338,7 +337,7 @@ Notification object contains:
338337
- **`fireDate`**- The date and time when the system should deliver the notification (optinal - default is immidiate dispatch).
339338
- `alertBody`- The message displayed in the notification alert.
340339
- `alertTitle`- The title of the notification, displayed in the notifications center.
341-
- `alertAction`- The "action" displayed beneath an actionable notification.
340+
- `alertAction`- The "action" displayed beneath an actionable notification on the lockscreen (e.g. "Slide to **open**"). Note that Apple no longer shows this in iOS 10.
342341
- `soundName`- The sound played when the notification is fired (optional).
343342
- `category`- The category of this notification, required for [interactive notifications](#interactive--actionable-notifications-ios-only) (optional).
344343
- `userInfo`- An optional object containing additional notification data.
@@ -357,16 +356,16 @@ NotificationsAndroid.localNotification({
357356

358357
Upon notification opening (tapping by the device user), all data fields will be delivered as-is).
359358

360-
### Cancel Local Notification
361-
The `NotificationsIOS.localNotification()` and `NotificationsAndroid.localNotification()` methods return unique `notificationId` values, which can be used in order to cancel specific local notifications. You can cancel local notification by calling `NotificationsIOS.cancelLocalNotification(notificationId)` or `NotificationsAndroid.cancelLocalNotification(notificationId)`.
359+
### Cancel Scheduled Local Notifications
360+
361+
The `NotificationsIOS.localNotification()` and `NotificationsAndroid.localNotification()` methods return unique `notificationId` values, which can be used in order to cancel specific local notifications that were scheduled for delivery on `fireDate` and have not yet been delivered. You can cancel local notification by calling `NotificationsIOS.cancelLocalNotification(notificationId)` or `NotificationsAndroid.cancelLocalNotification(notificationId)`.
362362

363363
Example (iOS):
364364

365365
```javascript
366366
let someLocalNotification = NotificationsIOS.localNotification({
367367
alertBody: "Local notificiation!",
368368
alertTitle: "Local Notification Title",
369-
alertAction: "Click here to open",
370369
soundName: "chime.aiff",
371370
category: "SOME_CATEGORY",
372371
userInfo: { }
@@ -375,12 +374,26 @@ let someLocalNotification = NotificationsIOS.localNotification({
375374
NotificationsIOS.cancelLocalNotification(someLocalNotification);
376375
```
377376

378-
### Cancel All Local Notifications (iOS-only!)
377+
To cancel all local notifications (**iOS only!**), use `cancelAllLocalNotifications()`:
379378

380379
```javascript
381380
NotificationsIOS.cancelAllLocalNotifications();
382381
```
383382

383+
### Cancel Delivered Local Notifications (iOS 10+ only)
384+
385+
To dismiss notifications from the notification center that have already been shown to the user, call `NotificationsIOS.removeDeliveredNotifications([notificationId])`:
386+
387+
```javascript
388+
let someLocalNotification = NotificationsIOS.localNotification({...});
389+
390+
NotificationsIOS.removeDeliveredNotifications([someLocalNotification]);
391+
```
392+
393+
Call `removeAllDeliveredNotifications()` to dismiss all delivered notifications
394+
(note that this will dismiss push notifications in addition to local
395+
notifications).
396+
384397
---
385398

386399
## Managed Notifications (iOS only)
@@ -444,13 +457,13 @@ Now the server should push the notification a bit differently- background instea
444457
445458
### getDeliveredNotifications
446459
447-
`PushNotification.getDeliveredNotifications(callback: (notifications: [Object]) => void)`
460+
`PushNotification.getDeliveredNotifications(callback: (notifications: Array<Object>) => void)`
448461
449462
Provides you with a list of the app’s notifications that are still displayed in Notification Center.
450463
451464
### removeDeliveredNotifications
452465
453-
`PushNotification.removeDeliveredNotifications(identifiers: [string])`
466+
`PushNotification.removeDeliveredNotifications(identifiers: Array<String>)`
454467
455468
Removes the specified notifications from Notification Center.
456469

RNNotifications/RNNotifications.m

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#import "RNNotificationsBridgeQueue.h"
1818
#import <UserNotifications/UserNotifications.h>
1919

20+
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
21+
2022
NSString* const RNNotificationCreateAction = @"CREATE";
2123
NSString* const RNNotificationClearAction = @"CLEAR";
2224

@@ -108,26 +110,58 @@ + (UILocalNotification *)UILocalNotification:(id)json
108110
}
109111
@end
110112

113+
@implementation RCTConvert (UNNotificationRequest)
114+
+ (UNNotificationRequest *)UNNotificationRequest:(id)json withId:(NSString*)notificationId
115+
{
116+
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
117+
118+
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
119+
content.body = [RCTConvert NSString:details[@"alertBody"]];
120+
content.title = [RCTConvert NSString:details[@"alertTitle"]];
121+
content.sound = [RCTConvert NSString:details[@"soundName"]]
122+
? [UNNotificationSound soundNamed:[RCTConvert NSString:details[@"soundName"]]]
123+
: [UNNotificationSound defaultSound];
124+
content.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]] ?: @{};
125+
content.categoryIdentifier = [RCTConvert NSString:details[@"category"]];
126+
127+
NSDate *triggerDate = [RCTConvert NSDate:details[@"fireDate"]];
128+
UNCalendarNotificationTrigger *trigger = nil;
129+
if (triggerDate != nil) {
130+
NSDateComponents *triggerDateComponents = [[NSCalendar currentCalendar]
131+
components:NSCalendarUnitYear +
132+
NSCalendarUnitMonth + NSCalendarUnitDay +
133+
NSCalendarUnitHour + NSCalendarUnitMinute +
134+
NSCalendarUnitSecond + NSCalendarUnitTimeZone
135+
fromDate:triggerDate];
136+
trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:triggerDateComponents
137+
repeats:NO];
138+
}
139+
140+
return [UNNotificationRequest requestWithIdentifier:notificationId
141+
content:content trigger:trigger];
142+
}
143+
@end
144+
111145
static NSDictionary *RCTFormatUNNotification(UNNotification *notification)
112146
{
113147
NSMutableDictionary *formattedNotification = [NSMutableDictionary dictionary];
114148
UNNotificationContent *content = notification.request.content;
115149

116150
formattedNotification[@"identifier"] = notification.request.identifier;
117-
151+
118152
if (notification.date) {
119153
NSDateFormatter *formatter = [NSDateFormatter new];
120154
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"];
121155
NSString *dateString = [formatter stringFromDate:notification.date];
122156
formattedNotification[@"fireDate"] = dateString;
123157
}
124-
158+
125159
formattedNotification[@"alertTitle"] = RCTNullIfNil(content.title);
126160
formattedNotification[@"alertBody"] = RCTNullIfNil(content.body);
127161
formattedNotification[@"category"] = RCTNullIfNil(content.categoryIdentifier);
128162
formattedNotification[@"thread-id"] = RCTNullIfNil(content.threadIdentifier);
129163
formattedNotification[@"userInfo"] = RCTNullIfNil(RCTJSONClean(content.userInfo));
130-
164+
131165
return formattedNotification;
132166
}
133167

@@ -545,25 +579,35 @@ - (void)handleNotificationActionTriggered:(NSNotification *)notification
545579

546580
RCT_EXPORT_METHOD(localNotification:(NSDictionary *)notification withId:(NSString *)notificationId)
547581
{
548-
UILocalNotification* localNotification = [RCTConvert UILocalNotification:notification];
549-
NSMutableArray* userInfo = localNotification.userInfo.mutableCopy;
550-
[userInfo setValue:notificationId forKey:@"__id"];
551-
localNotification.userInfo = userInfo;
552-
553-
if ([notification objectForKey:@"fireDate"] != nil) {
554-
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
582+
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10")) {
583+
UNNotificationRequest* localNotification = [RCTConvert UNNotificationRequest:notification withId:notificationId];
584+
[[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:localNotification withCompletionHandler:nil];
555585
} else {
556-
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
586+
UILocalNotification* localNotification = [RCTConvert UILocalNotification:notification];
587+
NSMutableArray* userInfo = localNotification.userInfo.mutableCopy;
588+
[userInfo setValue:notificationId forKey:@"__id"];
589+
localNotification.userInfo = userInfo;
590+
591+
if ([notification objectForKey:@"fireDate"] != nil) {
592+
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
593+
} else {
594+
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
595+
}
557596
}
558597
}
559598

560599
RCT_EXPORT_METHOD(cancelLocalNotification:(NSString *)notificationId)
561600
{
562-
for (UILocalNotification* notification in [UIApplication sharedApplication].scheduledLocalNotifications) {
563-
NSDictionary* notificationInfo = notification.userInfo;
601+
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10")) {
602+
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
603+
[center removePendingNotificationRequestsWithIdentifiers:@[notificationId]];
604+
} else {
605+
for (UILocalNotification* notification in [UIApplication sharedApplication].scheduledLocalNotifications) {
606+
NSDictionary* notificationInfo = notification.userInfo;
564607

565-
if ([[notificationInfo objectForKey:@"__id"] isEqualToString:notificationId]) {
566-
[[UIApplication sharedApplication] cancelLocalNotification:notification];
608+
if ([[notificationInfo objectForKey:@"__id"] isEqualToString:notificationId]) {
609+
[[UIApplication sharedApplication] cancelLocalNotification:notification];
610+
}
567611
}
568612
}
569613
}
@@ -576,7 +620,7 @@ - (void)handleNotificationActionTriggered:(NSNotification *)notification
576620
RCT_EXPORT_METHOD(isRegisteredForRemoteNotifications:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
577621
{
578622
BOOL ans;
579-
623+
580624
if (TARGET_IPHONE_SIMULATOR) {
581625
ans = [[[UIApplication sharedApplication] currentUserNotificationSettings] types] != 0;
582626
}
@@ -620,7 +664,7 @@ - (void)handleNotificationActionTriggered:(NSNotification *)notification
620664
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
621665
[center getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
622666
NSMutableArray<NSDictionary *> *formattedNotifications = [NSMutableArray new];
623-
667+
624668
for (UNNotification *notification in notifications) {
625669
[formattedNotifications addObject:RCTFormatUNNotification(notification)];
626670
}

index.ios.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ export default class NotificationsIOS {
229229
*
230230
* @param identifiers Array of notification identifiers
231231
*/
232-
static removeDeliveredNotifications(identifiers: [string]) {
232+
static removeDeliveredNotifications(identifiers: Array<String>) {
233233
return NativeRNNotifications.removeDeliveredNotifications(identifiers);
234234
}
235235

@@ -248,7 +248,7 @@ export default class NotificationsIOS {
248248
* - `thread-id` : The thread identifier of this notification, if has one.
249249
* - `fireDate` : The date and time when the system should deliver the notification. if not specified, the notification will be dispatched immediately.
250250
*/
251-
static getDeliveredNotifications(callback: (notifications: [Object]) => void) {
251+
static getDeliveredNotifications(callback: (notifications: Array<Object>) => void) {
252252
return NativeRNNotifications.getDeliveredNotifications(callback);
253253
}
254254
}

0 commit comments

Comments
 (0)