Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ios): cancel pending local notifications (8_0_X) #10583

Merged
merged 2 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions apidoc/Titanium/App/iOS/UserNotificationCenter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,31 @@ methods:
Removes the specified pending notifications to prevent them from being triggered.
If no notifications are specified, all pending notifications will be removed.
description: |
Pending notifications can be obtained via a call to the <Titanium.App.iOS.UserNotificationCenter.getDeliveredNotifications>
Pending notifications can be obtained via a call to the <Titanium.App.iOS.UserNotificationCenter.getPendingNotifications>
method.
since: "7.3.0"
parameters:
- name: notifications
summary: |
The pending notification to remove. If none specified, all pending notifications
will be removed.
type: Array<Titanium.App.iOS.LocalNotification>
type: Array<UserNotificationDictionary>

- name: removeDeliveredNotifications
summary: |
Removes the specified delivered notifications from the notification-center.
If no notifications are specified, all delivered notifications will be removed.
description: |
Delivered notifications can be obtained via a call to the <Titanium.App.iOS.UserNotificationCenter.getDeliveredNotifications>
method.
osver: {ios: {min: "10.0"}}
since: "7.3.0"
parameters:
- name: notifications
summary: |
The delivered notification to remove. If none specified, all pending notifications
will be removed.
type: Array<UserNotificationDictionary>

- name: requestUserNotificationSettings
summary: |
Expand Down Expand Up @@ -138,9 +147,9 @@ properties:
- name: identifier
summary: The notification identifier.
description: |
This property is required in iOS 10+ and will fallback to a generated
UUID-string if not set. It is recommended to manage the identifier
yourself, but you can also get the generated UUID by accessing via
This property is required in iOS 10+ and will fallback to a generated
UUID-string if not set. It is recommended to manage the identifier
yourself, but you can also get the generated UUID by accessing via
the "userInfo.id" field for parity with older iOS versions.
optional: false
since: "7.3.0"
Expand Down
43 changes: 25 additions & 18 deletions iphone/Classes/TiAppiOSProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,13 @@ - (TiAppiOSLocalNotificationProxy *)scheduleLocalNotification:(id)args
NSNumber *summaryArgumentCount = [args objectForKey:@"summaryArgumentCount"];
NSString *threadIdentifier = [TiUtils stringValue:@"threadIdentifier" properties:args];
NSString *timezone = [TiUtils stringValue:@"timezone" properties:args];
NSString *identifier = [TiUtils stringValue:@"identifier" properties:args def:NSUUID.UUID.UUIDString];

// Construct a new local notification proxy from our current context
TiAppiOSLocalNotificationProxy *notification = [[[TiAppiOSLocalNotificationProxy alloc] _initWithPageContext:[self executionContext]] autorelease];

// For iOS 10+, use the UserNotifications framework to manage notification
if ([TiUtils isIOSVersionOrGreater:@"10.0"]) {
NSString *identifier = [TiUtils stringValue:@"identifier" properties:args def:NSUUID.UUID.UUIDString];
NSString *alertSubtitle = [TiUtils stringValue:@"alertSubtitle" properties:args];
NSString *category = [TiUtils stringValue:@"category" properties:args];
NSArray<NSDictionary<NSString *, id> *> *attachments = [args objectForKey:@"attachments"];
Expand Down Expand Up @@ -754,20 +754,7 @@ - (TiAppiOSLocalNotificationProxy *)scheduleLocalNotification:(id)args
}

// Set additional user-info
if (userInfo != nil) {
// If user-info exists, but the "id" field does not, inject it
if ([userInfo objectForKey:@"id"] == nil) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:userInfo];
[dict setObject:identifier forKey:@"id"];
[content setUserInfo:dict];
} else {
// If user-info and "id" field exist, simply assign
[content setUserInfo:userInfo];
}
} else {
// If no user-info exists at all, inject the "id" field
[content setUserInfo:@{ @"id" : identifier }];
}
[self assignUserInfo:userInfo toContent:content ensureIdentifier:identifier];

// Set attachments
if (attachments != nil) {
Expand Down Expand Up @@ -928,9 +915,8 @@ - (TiAppiOSLocalNotificationProxy *)scheduleLocalNotification:(id)args
}
}

if (userInfo) {
content.userInfo = userInfo;
}
// Set additional user-info
[self assignUserInfo:userInfo toContent:content ensureIdentifier:identifier];

id category = [args objectForKey:@"category"];
if (category != nil && [category isKindOfClass:[TiAppiOSUserNotificationCategoryProxy class]]) {
Expand All @@ -955,6 +941,27 @@ - (TiAppiOSLocalNotificationProxy *)scheduleLocalNotification:(id)args
}
}

/**
Assign custom user info to notification content and make sure it has an identifier.
@param userInfo User info dictionary to assign to the notification content
@param content Notification content, can either be UNMutableNotificationContent or UILocalNotification
@param notificationIdentifier The unique idenitifer for a notification.
*/
- (void)assignUserInfo:(NSDictionary *)userInfo toContent:(id)content ensureIdentifier:(NSString *)notificationIdentifier
{
NSMutableDictionary *userInfoWithId = userInfo == nil ? @{ @"id" : notificationIdentifier } : userInfo.mutableCopy;
if (userInfoWithId[@"id"] == nil) {
userInfoWithId[@"id"] = notificationIdentifier;
}

if ([content isKindOfClass:UNMutableNotificationContent.class]) {
((UNMutableNotificationContent *)content).userInfo = userInfoWithId;
} else if ([content isKindOfClass:UILocalNotification.class]) {
((UILocalNotification *)content).userInfo = userInfoWithId;
}
}

- (void)cancelAllLocalNotifications:(id)unused
{
ENSURE_UI_THREAD(cancelAllLocalNotifications, unused);
Expand Down
48 changes: 28 additions & 20 deletions iphone/Classes/TiAppiOSUserNotificationCenterProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ - (void)getPendingNotifications:(id)callback
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[notifications count]];

for (UILocalNotification *notification in notifications) {
[result addObject:[TiApp dictionaryWithLocalNotification:notification withIdentifier:nil]];
[result addObject:[TiApp dictionaryWithLocalNotification:notification withIdentifier:notification.userInfo[@"id"]]];
}

NSDictionary *propertiesDict = @{
Expand Down Expand Up @@ -90,7 +90,7 @@ - (void)getDeliveredNotifications:(id)callback

- (void)removePendingNotifications:(id)args
{
ENSURE_TYPE_OR_NIL(args, NSArray);
ENSURE_SINGLE_ARG_OR_NIL(args, NSArray);

if ([TiUtils isIOSVersionOrGreater:@"10.0"]) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
Expand All @@ -101,18 +101,19 @@ - (void)removePendingNotifications:(id)args
}

[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
// Loop through current notification requests
NSMutableArray<NSString *> *identifiers = [NSMutableArray new];
for (UNNotificationRequest *request in requests) {

// Loop through provided notifications
for (id notification in args) {
ENSURE_TYPE(notification, TiAppiOSLocalNotificationProxy);
ENSURE_TYPE(notification, NSDictionary);

if ([request content] == [(TiAppiOSLocalNotificationProxy *)notification notification]) {
[center removePendingNotificationRequestsWithIdentifiers:@[ [request identifier] ]];
if ([request.identifier isEqual:notification[@"identifier"]]) {
[identifiers addObject:request.identifier];
}
}
}
if (identifiers.count > 0) {
[center removePendingNotificationRequestsWithIdentifiers:identifiers];
}
}];
},
NO);
Expand All @@ -123,9 +124,15 @@ - (void)removePendingNotifications:(id)args
return;
}

for (id notification in args) {
ENSURE_TYPE(notification, TiAppiOSLocalNotificationProxy);
[[UIApplication sharedApplication] cancelLocalNotification:[(TiAppiOSLocalNotificationProxy *)notification notification]];
for (UILocalNotification *scheduledNotification in UIApplication.sharedApplication.scheduledLocalNotifications) {
for (id notification in args) {
ENSURE_TYPE(notification, NSDictionary);

if ([notification[@"userInfo"][@"id"] isEqual:scheduledNotification.userInfo[@"id"]]) {
[UIApplication.sharedApplication cancelLocalNotification:scheduledNotification];
break;
}
}
}
},
NO);
Expand All @@ -134,7 +141,7 @@ - (void)removePendingNotifications:(id)args

- (void)removeDeliveredNotifications:(id)args
{
ENSURE_TYPE_OR_NIL(args, NSArray);
ENSURE_SINGLE_ARG_OR_NIL(args, NSArray);

if ([TiUtils isIOSVersionOrGreater:@"10.0"]) {
TiThreadPerformOnMainThread(^{
Expand All @@ -145,19 +152,20 @@ - (void)removeDeliveredNotifications:(id)args
return;
}

[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
// Loop through current notification requests
for (UNNotificationRequest *request in requests) {

// Loop through provided notifications
[center getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *notifications) {
NSMutableArray<NSString *> *identifiers = [NSMutableArray new];
for (UNNotification *deliveredNotification in notifications) {
for (id notification in args) {
ENSURE_TYPE(notification, TiAppiOSLocalNotificationProxy);
ENSURE_TYPE(notification, NSDictionary);

if ([request content] == [(TiAppiOSLocalNotificationProxy *)notification notification]) {
[center removeDeliveredNotificationsWithIdentifiers:@[ [request identifier] ]];
if ([deliveredNotification.request.identifier isEqual:notification[@"identifier"]]) {
[identifiers addObject:deliveredNotification.request.identifier];
}
}
}
if (identifiers.count > 0) {
[center removeDeliveredNotificationsWithIdentifiers:identifiers];
}
}];
},
NO);
Expand Down
2 changes: 1 addition & 1 deletion iphone/TitaniumKit/TitaniumKit/Sources/API/TiApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -1541,7 +1541,7 @@ + (NSDictionary *)dictionaryWithLocalNotification:(UILocalNotification *)notific
}
+ (NSDictionary *)dictionaryWithLocalNotification:(UILocalNotification *)notification
{
return [self dictionaryWithLocalNotification:notification withIdentifier:nil];
return [self dictionaryWithLocalNotification:notification withIdentifier:notification.userInfo[@"id"]];
}

// Returns an NSDictionary with the properties from tiapp.xml
Expand Down