Extensions Framework
Contents
The iOS Extensions Framework is a new addition to the Sailthru Mobile iOS SDK that allows apps to save events in app extensions - https://developer.apple.com/app-extensions/.
Extensions only have access to a limited set of the iOS APIs, so it's not possible to use the main Sailthru Mobile iOS SDK Framework in an extension. To solve this we have developed the Extensions Framework specifically to operate in app extensions in order to allow you to properly integrate them with the Sailthru Mobile platform.App Groups
In order for the Extension Framework to communicate with the main Sailthru Mobile iOS SDK your app needs to set up an App Group (https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups?language=objc). App groups allow apps and extensions to share an NSUserDefaults instance. You can set up an App Group in the Apple Developer site (https://developer.apple.com/) in the Certificates, Identities and Profiles section.
Adding the Extensions Framework
Swift Package Manager
If you are using Swift Package Manager you will see the extension SDK as an option to add to your project when you add SailthruMobile as a dependency. This will add it automatically to your main app target. You should then manually add it to the list of linked binaries in your extensions targets.Cocoapods
If you are using Cocoapods you should add the Extension Framework to your main app target and to any extension targets like so:target 'YourAppExtension' do
pod 'SailthruMobile-Extension', '12.0.0'
end
The extension is a subspec of the main SDK pod so it will be automatically added to your main app target.
Carthage
If you import the SDK as normal using Carthage you will notice that the SailthruMobile.framework file contains both the main SailthruMobile.xcframework and the SailthruMobileExtension.xcframework. You should add both frameworks to your main app and the extensions framework to any app extensions that you plan to use it in.Manually
If you add the Frameworks manually then you will find the SailthruMobileExtension.framework bundled next to the main SailthruMobile.framework. You should ensure this is added to your Extension target and to your app target. Note:The Extensions Framework needs to be embedded in your main app target as well as added to the Extension Target. If you are not setting up the SDK with Cocoapods you must ensure the Extension Framework is added to both targets.Setting up the Framework
Once the Extensions Framework has been added you will need to initialize it both in the main app and in the extension.Main App
In the main app you simply need to register any shared App Groups that you have created:iOS (Objective-C)
[[SailthruMobile new] registerExtensionGroups:@[@"group.your.group.name"]];
iOS (Swift)
SailthruMobile().registerExtensionGroups(["group.your.group.name"])
Extensions
The Extensions Framework is primarily designed to work with the UNNotificationServiceExtension and UNNotificationContentExtension extensions.UNNotificationServiceExtension
In order to simplify the UNNotificationServiceExtension integration we have created our own implementation that you can use to quickly and easily set up both the Extensions Framework and Rich Push Notification handling:iOS (Objective-C)
#import "NotificationService.h"
#import <SailthruMobileExtension/STMNotificationServiceExtension.h>
@interface NotificationService ()
@property (nonatomic, strong) STMNotificationServiceExtension *stmServiceExtension;
@end
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
// setup sailthru service extension
self.stmServiceExtension = [[STMNotificationServiceExtension alloc] initWithAppKey:@"YOUR_APP_KEY" andGroupName:@"group.your.group.name"];
// handle notification request
[self.stmServiceExtension didReceiveNotificationRequest:request withContentHandler:contentHandler];
}
- (void)serviceExtensionTimeWillExpire {
// handle extension timeout
[self.stmServiceExtension serviceExtensionTimeWillExpire];
}
@end
iOS (Swift)
import UserNotifications
import SailthruMobileExtension
class NotificationService: UNNotificationServiceExtension {
var sailthruNotificationServiceExtension : STMNotificationServiceExtension?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler:@escaping (UNNotificationContent) -> Void) {
// setup sailthru service extension
self.sailthruNotificationServiceExtension = STMNotificationServiceExtension(appKey: "YOUR_APP_KEY", andGroupName: "group.your.group.name")
// handle notification request
self.sailthruNotificationServiceExtension?.didReceive(request, withContentHandler: contentHandler)
}
override func serviceExtensionTimeWillExpire() {
// handle extension timeout
self.sailthruNotificationServiceExtension?.serviceExtensionTimeWillExpire()
}
}
iOS (Objective-C)
@property (nullable, nonatomic, strong) SailthruMobileExtension *extension;
@property (nullable, nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
// retrieve instance for app group
self.extension = [[SailthruMobileExtension alloc] initWithAppKey:@"YOUR_APP_KEY" groupName:@"group.your.group.name"];
// handle notification request
[self.extension handleNotificationRequest:request];
// Register any custom events
[self.extension logEvent:@"my event"];
// Continue as normal
}
iOS (Swift)
var extension : SailthruMobileExtension?
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
var downloadTask: URLSessionDownloadTask?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler:@escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
self.extension = SailthruMobileExtension(appKey: "YOUR_APP_KEY", groupName: "group.your.group.name")
// handle notification request
self.extension?.handleNotificationRequest(request)
// Register any custom events
self.extension?.logEvent("my event")
// Continue as normal
}
UNNotificationContentExtension
In the UNNotificationContentExtension you should start the engine and retrieve the instance in theviewDidLoad
method and the use the extension to handle the notification when it is received:
iOS (Objective-C)
@property (strong, nonatomic) SailthruMobileExtension *extension;
@implementation NotificationViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.extension = [[SailthruMobileExtension alloc] initWithAppKey:@"YOUR_APP_KEY" groupName:@"group.your.group.name"];
}
- (void)didReceiveNotification:(UNNotification *)notification {
// handle notification
[self.extension handleNotification:notification];
// Register any custom events
[self.extension logEvent:@"my event"];
// Continue as normal
}
iOS (Swift)
var extension : SailthruMobileExtension?
@implementation NotificationViewController
override func viewDidLoad() {
super.viewDidLoad()
self.extension = SailthruMobileExtension(appKey: "YOUR_APP_KEY", groupName: "group.your.group.name")
}
- (void)didReceiveNotification:(UNNotification *)notification {
// handle notification
self.extension?.handleNotification(notification)
// Register any custom events
self.extension?.logEvent("my event")
// Continue as normal
}