Latest 2.0.1
Homepage https://github.com/T-Pham/UILocalNotification-RemotePayload
License MIT
Platforms ios 8.2, watchos 2.0
Frameworks UIKit
Authors
'   _     _  _     ____  ____  ____  _     _      ____  _____  _  _____ _  ____  ____  _____  _  ____  _     
'  /  // /    /  _ /   _/  _ /    /   /|/  _ /__ __/ /    // /   _/  _ /__ __/ /  _ /   /|
'  | | ||| || |   | / ||  /  | / || |   | | ||| / |  /   | ||  __| ||  /  | / |  /   | || / || | ||
'  | _/|| || |_/| _/||  _ | |-||| |_/| | ||| _/|  | |  | || |   | ||  _ | |-||  | |  | || _/|| | ||
'  ____/_/____/____/____/_/ |____/_/  |____/  _/  _/_/   _/____/_/ |  _/  _/____/_/  |
'                                                                                                            
'   ____  _____ _      ____  _____  _____ ____  ____ ___  _ _     ____  ____  ____                           
'  /  __/  __// __/|/  _ /__ __/  __//  __/  _ \  ///    /  _ /  _ /  _                           
'  |  /||    | |/||| / |  /   |    |  /|| / |   / | |   | / || / || | |                          
'  |    /|  /_ | |  ||| _/|  | |  |  /_ |  __/| |-|| / /  | |_/| _/|| |-||| |_/|                          
'  _/_\____\_/  |____/  _/  ____\_/   _/ |/_/   ____/____/_/ |____/                          
'                                                                                                            

CI Status
GitHub issues
Codecov
Documentation

GitHub release
Platform
License

Carthage

CocoaPods
CocoaPods downloads

Description

The extension provides a convenient init method to create UILocalNotification instance from remote payload specified in Apple’s Documentation.

It is motivated by the fact that we have more control over local notifications than remote notifications. With local notifications, we can have notifications with behaviours as seen in apps such as Gmail or Facebook Messenger. The Gmail app can clear the notifications of read emails on your iOS device automatically when you have read the emails on a browser. The Messenger app’s notification for incoming calls can vibrate and play sound repeatedly without flooding your screen with multiple notifications. Google and Facebook might not use the same technique being discussed here, but we can have notifications with those advanced behaviours for our own apps using the technique explained below.

The idea is, instead of pushing a remote notification and having iOS displayed it to user, we push a silent notification which will invoke our app in the background, then the background code constructs a local notification from the payload and display it to user. Since we hold the local notification instance, we can remove it from the screen whenever we want. The technique only works when Background App Refresh is enabled on user’s device and your app have registered background execution. However, if your app is a VoIP app using PushKit, the technique works even when Background App Refresh is disabled.

Set-up

  • Enable background mode in your app’s Info.plist file:
Non-VoIP app:

“`plist
UIBackgroundModesremote-notification
“`

VoIP app:

“`plist
UIBackgroundModesvoip
“`

  • Register for local notification permission:
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Badge, .Sound, .Alert], categories: nil))
  • Register for remote notification:
Non-VoIP app:

“`swift
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types != .None {
application.registerForRemoteNotifications()
}
}

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
// pass the deviceToken to the server
}
“`

VoIP app:

“`swift
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types != .None {
let pushRegistry = PKPushRegistry(queue: dispatch_get_main_queue())
pushRegistry.delegate = self
pushRegistry.desiredPushTypes = [PKPushTypeVoIP]
}
}
“`

“`swift
extension AppDelegate: PKPushRegistryDelegate {

func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// pass credentials.token to the server
}
}
“`

  • Push a notification from the server. You may want to assign it an id, so you can add the logic to update notifications based on their id.
Non-VoIP app:

Push a silent remote notification. Put the payload to an object other than the top-level `aps` so that the notification remains silent. Here we put it in the `payload` object.

“`json
{
“aps” : {
“content-available”: 1
},
“payload” : {
“aps” : {
“alert” : “hello world”
},
“id” : 1
}
}
“`

VoIP app:

Just push a normal payload because VoIP notifications are always silent.

“`json
{
“aps” : {
“alert” : “hello world”
},
“id” : 1
}
“`

  • Handle the remote notification:
Non-VoIP app:

“`swift
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
let localNotification = UILocalNotification(remotePayload: userInfo[“payload”] as? [NSObject: AnyObject] ?? [:])
if let id = userInfo[“payload”]?[“id”] as? Int {
if let previousLocalNotification = self.localNotificationsMap[id] {
UIApplication.sharedApplication().cancelLocalNotification(previousLocalNotification)
}
self.localNotificationsMap[id] = localNotification
}
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
completionHandler(.NoData)
}
“`

VoIP app:

“`swift
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
let localNotification = UILocalNotification(remotePayload: payload.dictionaryPayload)
if let id = payload.dictionaryPayload[“id”] as? Int {
if let previousLocalNotification = self.localNotificationsMap[id] {
UIApplication.sharedApplication().cancelLocalNotification(previousLocalNotification)
}
self.localNotificationsMap[id] = localNotification
}
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
“`

Usage

Swift:

“`swift
let localNotification = UILocalNotification(remotePayload: remotePayload)
“`

Objective-C:

“`objective-c
UILocalNotification *localNotification = [[UILocalNotification alloc] initWithRemotePayload:remotePayload];
“`

Installation

Carthage

Add the line below to your Cartfile:

github "T-Pham/UILocalNotification-RemotePayload"

CocoaPods

Add the line below to your Podfile:

pod 'UILocalNotification-RemotePayload'

Manually

Add the file /UILocalNotification-RemotePayload/UILocalNotification-RemotePayload.swift to your project. You are all set.

Compatibility

From version 2.0.0, Swift 3 syntax is used. If your project is still using Swift version 2, please use a UILocalNotification-RemotePayload version prior to 2.0.0.

Podfile

pod 'UILocalNotification-RemotePayload', '~> 1.0.4'

or Cartfile

github "T-Pham/UILocalNotification-RemotePayload" ~> 1.0.4

License

UILocalNotification-RemotePayload is available under the MIT license. See the LICENSE file for more info.

Latest podspec

{
    "name": "UILocalNotification-RemotePayload",
    "version": "2.0.1",
    "summary": "Gmail & Facebook Messenger-like notifications.",
    "description": "UILocalNotification-RemotePayload provides a method to create UILocalNotification from remote notification payload. It is helpful because you have more control over local notifications than remote notifications. Please see the README for the details.",
    "homepage": "https://github.com/T-Pham/UILocalNotification-RemotePayload",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Thanh Pham": "[email protected]"
    },
    "source": {
        "git": "https://github.com/T-Pham/UILocalNotification-RemotePayload.git",
        "tag": "2.0.1"
    },
    "platforms": {
        "ios": "8.2",
        "watchos": "2.0"
    },
    "source_files": "UILocalNotification-RemotePayload/*.swift",
    "frameworks": "UIKit"
}

Pin It on Pinterest

Share This