Skip to content

Commit

Permalink
Using reflection to add the UNNotificationActionIcon
Browse files Browse the repository at this point in the history
This is pretty ugly because we cannot use performSelector withObject. That method only allows up to 2 arguments so we must use NSInvocation.
  • Loading branch information
emawby committed Sep 13, 2021
1 parent d4859c1 commit dda1993
Showing 1 changed file with 37 additions and 11 deletions.
48 changes: 37 additions & 11 deletions iOS_SDK/OneSignalSDK/Source/OneSignalHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -567,20 +567,46 @@ + (UNNotificationRequest*)prepareUNNotificationRequest:(OSNotification*)notifica
}

+ (UNNotificationAction *)createActionForButton:(NSDictionary *)button {
NSString *buttonId = button[@"id"];
NSString *buttonText = button[@"text"];

if (@available(iOS 15.0, *)) {
UNNotificationActionIcon *icon;
if (button[@"systemIcon"]) {
icon = [UNNotificationActionIcon iconWithSystemImageName:button[@"systemIcon"]];
} else if (button[@"templateIcon"]) {
icon = [UNNotificationActionIcon iconWithTemplateImageName:button[@"templateIcon"]];
// Using reflection for Xcode versions lower than 13
id icon; // UNNotificationActionIcon
let UNNotificationActionIconClass = NSClassFromString(@"UNNotificationActionIcon");
if (UNNotificationActionIconClass) {
if (button[@"systemIcon"]) {
icon = [UNNotificationActionIconClass performSelector:@selector(iconWithSystemImageName:)
withObject:button[@"systemIcon"]];
} else if (button[@"templateIcon"]) {
icon = [UNNotificationActionIconClass performSelector:@selector(iconWithTemplateImageName:)
withObject:button[@"templateIcon"]];
}
}
return [UNNotificationAction actionWithIdentifier:button[@"id"]
title:button[@"text"]
options:UNNotificationActionOptionForeground
icon:icon];

// We need to use NSInvocation because performSelector only allows up to 2 arguments
SEL actionSelector = NSSelectorFromString(@"actionWithIdentifier:title:options:icon:");
UNNotificationAction * __unsafe_unretained action;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UNNotificationAction methodSignatureForSelector:actionSelector]];
[invocation setTarget:[UNNotificationAction class]];
[invocation setSelector:actionSelector];
/*
From Apple's Documentation on NSInvocation:
Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively;
you should set these values directly with the target and selector properties.
Use indices 2 and greater for the arguments normally passed in a message.
*/
NSUInteger actionOption = UNNotificationActionOptionForeground;
[invocation setArgument:&buttonId atIndex:2];
[invocation setArgument:&buttonText atIndex:3];
[invocation setArgument:&actionOption atIndex:4];
[invocation setArgument:&icon atIndex:5];
[invocation invoke];
[invocation getReturnValue:&action];
return action;
} else {
return [UNNotificationAction actionWithIdentifier:button[@"id"]
title:button[@"text"]
return [UNNotificationAction actionWithIdentifier:buttonId
title:buttonText
options:UNNotificationActionOptionForeground];
}
}
Expand Down

0 comments on commit dda1993

Please sign in to comment.