Integration in iOS

Basic Integration

Integration in iOS is easy with our library. Our library can be added to any project using the popular CocoaPods system. We host our own cocoapods repository, so you have to add it to your sources by adding this line to your Podfile

source 'git@git.tickaroo.com:pub/CocoaPods.git'

Add the TikPushLib pod to your Podfile by inserting the following line where applicable:

pod 'TikPushLib'

After the Pod has installed, you need to add the following to your ApplicationDelegate to initialize the Push Library:

#import <TikPushLib/TikPushService.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  //...
  self.pushService = [TikPushService startWithToken:SUBSCRIBE_TOKEN];
  //...
}

SUBSCRIBE_TOKEN must be replaced with a valid subscribe token from the Admin UI. After that the push library is initialized and ready to work. The library will automatically acquire a push token if necessary and monitor token changes.

The returned TikPushService instance is a singleton and must be stored in a central place for later use.

Subscribing and Unsubscribing to Channels

The library contains a public API for channel management. All channel subscriptions will be stored offline and later synchronized with the server. For that reason all methods are synchronous, return quickly and can even be called on the main thread without hesitation.

The public API of the Push service contains the following methods for channel management:

/**
 * Subscribe to a channel without expiration date
 * 
 * Warning: It is not recommended to subscribe without expiration date!
 */
- (void)registerForChannel:(NSString *)channel;


/**
 * Subscribe to a channel with expiration date. The expiration will automatically be 
 * removed at the specified date
 */
- (void)registerForChannel:(NSString *)channel expiresAt:(NSDate *)expiresAt;

/**
 * Subscribe to a channel with expiration date. The expiration will automatically be 
 * removed at the specified date. If backgroundPush is set to true, the push library
 * will not ask for permission to display messages.
 */
- (void)registerForChannel:(NSString *)channel expiresAt:(NSDate *)expiresAt backgroundPush:(BOOL)backgroundPush;

/**
 * Removes a channel subscription
 */
- (void)unregisterForChannel:(NSString *)channel;

/**
 * Check if an active subscription exists. Changes made with register/unregister will
 * reflect immediately in this method, regardless if the subscription change has already
 * synced to the server
 */
- (BOOL)isRegisteredForChannel:(NSString *)channel;

/**
 * Removes all subscription. This is a last-resort failsafe call to reset pushes
 */
- (void)resetAllSubscriptions;

Reacting to Pushes

The library hooks into the default ApplicationDelegate methods for push notifications. As a default behaviour it displays notifications in the default iOS style whether the App is running or not. In addition to the defaults, the push library adds support for new delegate methods in you ApplicationDelegate to customize reaction to pushes.

Using the Push Library Defaults

If you are using the libraries default-behaviour of displaying a notification, it is possible to react to clicks on the notification by implementing the following method in your ApplicationDelegate:

- (void)application:(UIApplication *)application userDidTapRemoteNotification:(NSDictionary *)userInfo withActivationType:(TikPushNotificationActivationType)activationType;

This method will be called regardless if the user tapped on the notification within the app or on the home screen. The activationType will contains information about the origin, userInfo contains the received notification.

To customize the in-app notification, implement the following method in your ApplicationDelegate:

- (TikToastNotification *)application:(UIApplication *)application toastNotificationForRemoteNotification:(NSDictionary *)userInfo;

Notifications that are displayed while the app is not running can not be customized!

Custom Reaction to Pushes

To implement a custom reaction to pushes just implement the iOS standard method in your ApplicationDelegate. The default behaviour will not occur anymore.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;

Reacting to Errors

If the user has deactivated push notifications for the app, the ApplicationDelegate will receive a callback after a subscription request:

- (void)application:(UIApplication *)application userDidDeactivateRemoteNotifications:(NSArray *)failedSubscriptions;

This is a good place to show a dialog to the user encouraging him to go to settings and allow push notifications for the app.

Using new UNUserNotificationCenter (iOS 10)

For support of the new UNUserNotificationCenter and the custom views in the NotificationCenter you have to add at least two new Extensions to your Application, one additional for every additional custom view. Example Podfile:

 target 'YourNotificationExtension' do
	pod 'TikPushLib/NotificationExtensions'
end

target 'YourNotificationContentExtension1' do
  	pod 'TikPushLib/NotificationExtensions'
end

target 'YourNotificationContentExtension2' do
	pod 'TikPushLib/NotificationExtensions'
end
  • create your own TikPushContentFactory subclass.

Example using SDWebImage for displaying Images:

#import "TikPushContentFactory.h"

@interface PushContentFactory : TikPushContentFactory

@end

#import "PushContentFactory.h"
#import "TikPushNotificationContentView.h"
#import <SDWebImage/SDWebImageManager.h>
#import <SDWebImage/UIImageView+WebCache.h>


@interface PushContentView : TikPushNotificationContentView
@property (nonatomic) UILabel *lbl;
@property (nonatomic) UIImageView *imgView;

@end

@implementation PushContentFactory

- (UNMutableNotificationContent *)notificationContentForRemoteContent:(UNNotificationContent *)content attachmentsCompleteHandler:(void (^)(UNMutableNotificationContent *))complete {
    UNMutableNotificationContent *c = [super notificationContentForRemoteContent:content attachmentsCompleteHandler:complete];
    c.userInfo = @{@"someKey" : @"Details"};
    return c;
}

- (TikPushNotificationContentView *)viewForNotificationContentIdentifier:(NSString *)contentIdentifer {
    PushContentView * view = [[PushContentView alloc] initWithFrame:CGRectZero];
    if ([contentIdentifer isEqualToString:@"dummy1"]) {
        view.backgroundColor = [UIColor magentaColor];
    } else {
        view.backgroundColor = [UIColor cyanColor];
    }
    return view;
}

- (NSURL *)fileURLFromRemoteURL:(NSURL *)remoteUrl {
    NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:remoteUrl];
    NSString *path = [[SDImageCache sharedImageCache] defaultCachePathForKey:key];
    return [NSURL fileURLWithPath:path];
}

- (void)storeInCache:(NSData *)file remoteUrl:(NSURL *)remoteUrl {
    [[SDImageCache sharedImageCache] storeImageDataToDisk:file forKey:[[SDWebImageManager sharedManager] cacheKeyForURL:remoteUrl]];
}

@end

@implementation PushContentView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _imgView = [[UIImageView alloc] initWithFrame:frame];
        [self addSubview:_imgView];
    
        _lbl = [[UILabel alloc] initWithFrame:frame];
        _lbl.numberOfLines = 0;
        [self addSubview:_lbl];
    }
    return self;
}

- (void)didSetNotificationContent {
    [_imgView sd_setImageWithURL:[NSURL URLWithString:@"http://www.yolinux.com/TUTORIALS/images/YoLinux_logo.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        if (error) {
            _lbl.text = [error description];
        }
    }];
    [_lbl setText:[NSString stringWithFormat:@"userInfos: %@", self.notificationContent.userInfo]];
    self.resizeBlock(CGSizeMake(100, 300)); // Notify changes to the content-size so the view gets resized
}

- (void)layoutSubviews {
    _imgView.frame = self.bounds;
    _lbl.frame = self.bounds;
}

@end
  1. remove all files from the extensions, except the info.plist

  2. for http support add App Transport Security Settings to the extension info.plist(s)

  3. add “TikPushContentFactoryPrincipalClass” key with your TikPushContentFactory-subclass to info.plist(s), also to the app-plist

  4. add your TikPushContentFactory-subclass to the extension(s) target.

  5. set NSExtensionPrincipalClass in your NotificationContentExtension to TikPushNotificationContentViewController

  6. set NSExtensionPrincipalClass in your NotificationExtension to TikPushNotificationServiceExtension

Show the Notification when the Application is in foreground:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
    completionHandler(UNNotificationPresentationOptionAlert);
}

Use the same click-behavior in pre and post ios10 Devices

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)())completionHandler {
    [self application:[UIApplication sharedApplication] userDidTapRemoteNotification:response.notification.request.content.userInfo withActivationType:TikPushNotificationActivationTypeUserNotification];
    completionHandler();
}

Backend relevant infos:

files key is used for remote-images, if set, should be an array with dictionaries

url: http-url type: mime-type of the image/video file id: unique-identifier of the image/video

Include the mutable-content key with a value of 1.

Include an alert dictionary with subkeys for the title and body of the alert.

Include category key with an appropriate value in the aps dictionary

Other information can be provided using arbitrary keys. Frontend and Backend need to communicate this.