iOS 10 now allows Developers to modify the push payload before it is presented. To do that you need to create an new Application Extension called "Notification Service Extension".

1. Application Extension - Notification Service Extension

To create a new application extension select in xCode File -> New -> Target... and select Notification Service Extension.

1466

Screen Shot that you guys have added is for Notification Content. But for Rich push we need to add Notification Service Extension.

The App Extension must have it's own App ID and Provisioning Profile set up in the Apple Developer Center.

2. Configuring the Notification Service Extension

After creating the new App Extension you should have a new header file, objective-c file and plist. This is the default code that will work with Pulsate.

#import "NotificationService.h"

static NSString* const PulsateAttachmentUrl = @"au";
static NSString* const PulsateAttachmentType = @"at";

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@property (nonatomic, strong) UNMutableNotificationContent *notificationContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    self.notificationContent = [request.content mutableCopy];
    
    if (request.content.userInfo == nil) {
        [self defaultPushHandler];
        return;
    }
    
    if (request.content.userInfo[PulsateAttachmentType] == nil || request.content.userInfo[PulsateAttachmentUrl] == nil) {
        [self defaultPushHandler];
        return;
    }
    
    NSString* pulsateAttachment = request.content.userInfo[PulsateAttachmentUrl];
    NSString* pulsateAttachmentType = request.content.userInfo[PulsateAttachmentType];
    NSString *suffix = [@"." stringByAppendingString:pulsateAttachmentType];
    NSURL *pulsateAttachmentUrl = [NSURL URLWithString:pulsateAttachment];
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    [[session downloadTaskWithURL:pulsateAttachmentUrl
                completionHandler:^(NSURL *url, NSURLResponse *response, NSError *error) {
                    if (error != nil) {
                        [self defaultPushHandler];
                        return;
                    } else {
                        NSFileManager *fileManager = [NSFileManager defaultManager];
                        NSURL *typedUrl = [NSURL fileURLWithPath:[url.path stringByAppendingString:suffix]];
                        [fileManager moveItemAtURL:url toURL:typedUrl error:&error];
                        
                        NSError *error = nil;
                        UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:typedUrl options:nil error:&error];
                        if (attachment == nil) {
                            [self defaultPushHandler];
                            return;
                        }
                        self.bestAttemptContent.attachments = [NSArray arrayWithObjects:attachment, nil] ;
                        self.contentHandler(self.bestAttemptContent);
                    }
                }] resume];
}

- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    self.contentHandler(self.bestAttemptContent);
}

- (void)defaultPushHandler {
    self.contentHandler(self.bestAttemptContent);
}

@end
import UserNotifications

private let PulsateAttachmentUrl = "au"
private let PulsateAttachmentType = "at"
class NotificationService: UNNotificationServiceExtension {

    private var contentHandler: ((UNNotificationContent) -> Void)?
    private var bestAttemptContent: UNMutableNotificationContent?
    private var notificationContent: UNMutableNotificationContent?

    func defaultPushHandler() {
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        notificationContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if request.content.userInfo[PulsateAttachmentType] == nil || request.content.userInfo[PulsateAttachmentUrl] == nil {
            defaultPushHandler()
            return
        }
        
        let pulsateAttachment = request.content.userInfo[PulsateAttachmentUrl] as? String
        let pulsateAttachmentType = request.content.userInfo[PulsateAttachmentType] as? String
        let suffix = "." + (pulsateAttachmentType ?? "")
        let pulsateAttachmentUrl = URL(string: pulsateAttachment ?? "")
        
        do {
            let session = URLSession(configuration: URLSessionConfiguration.default)
            session.downloadTask(with: pulsateAttachmentUrl!, completionHandler: { location, response, error in
                if error != nil {
                    self.defaultPushHandler()
                    return
                } else {
                    let fileManager = FileManager.default
                    let typedUrl = URL(fileURLWithPath: location!.path + (suffix))
                    try? fileManager.moveItem(at: location!, to: typedUrl)
                    
                    let attachment = try? UNNotificationAttachment(identifier: "", url: typedUrl, options: nil)
                    if attachment == nil {
                        self.defaultPushHandler()
                        return
                    }
                    self.bestAttemptContent!.attachments = [attachment] as! [UNNotificationAttachment]
                    self.contentHandler!(self.bestAttemptContent!)
                }
            }).resume()
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}