iOS SDK Setup

Requirements

To use the messaging SDK, the following is required:

  • A registered Apple Developer account

  • Follow the installation steps:

  1. Configure CocoaPod

  2. Configure XCode Project

  3. Open the AppDelegate file of your project

Installation

Step 1: Configure CocoaPod

Open Terminal and start CocoaPod on the project that you are working on.

cd /YourProject
pod init
nano Podfile

Place the “MessagingLibrary” dependency.

platform :ios, '10.0'
target 'TestMessagingLibrary' do
  use_frameworks!
  platform :ios, '10.0'
  pod 'MessagingLibrary', '~> 1.0.0'
end

Run the installation or update command as appropriate.

pod install
# or
pod update

Open the workspace created by cocoapod for your project.

open YourProject.xcworkspace

Step 2: Configure XCode Project

Select your project and go to the Signatures and Capabilities tab.

Select a valid device to configure the following capabilities:

  • Add Push Notifications

  • Add Background modes and enable the following:

    Location updates

    Add Keychain Sharing and set a keychain group name

com.messaging.MessagingLibrary
1111

Step 3: Obtain Messaging-Info.plist file

Obtain the configuration file Messaging-Info.plist from the Mobile Messaging Platform. This is found in the Preferences section under the Push tab after completing the initial App Integration setup.

1144

Example of Messaging-Info.plist file:

<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>messagingHost</key><string>YourHost</string>
    <key>messagingAppToken</key><string>YourAppToken</string>
    <key>loggingEnable</key><false/>
    <key>locationEnable</key><false/>
    <key>analyticsEnable</key><false/>
  </dict>
</plist>

Once you have downloaded the required Messaging-Info.plist file, enter the following values:

  • messagingHost string: it must contain the URL and host version of messaging.

  • messagingAppToken string: access code granted by messaging.

  • loggingEnable boolean: variable to activate or deactivate the logs from the SDK

  • locationEnable boolean: variable to activate or deactivate Location use in the SDK.

  • analyticsEnable boolean: variable to activate or deactivate the Analytics use in the SDK.

Step 4: Open the AppDelegate project file

To do this, modify your delegate app with the following imports and methods.

import MessagingLibrary
@UIApplicationMain
class AppDelegate: MessagingAppDelegate {
 
 // It is executed when the user interacts with a notification.
 override func messagingInteractionNotification(_ notification: MessagingNotification) {
   // your code
 }
 
 // It is executed when a notification is received which allows operations to be performed without user interaction.
 override func messagingReceivedNotification(_ notification: MessagingNotification) -> UNNotificationPresentationOptions {
   // your code
   // if true
   //   return [.alert, .sound] // shows the notification on foreground.
   // else
   //   return [] // does not show the foreground notification.
   return [.alert, .sound] // for this example it will always be shown.
 }
 
 // Requesting permissions to receive notifications when you open the app by overwriting the messagingDidInitialized function inherited from MessagingAppDelegate.
 override func messagingDidInitialized(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
   // utility to request permissions to receive notifications
   Messaging.shared.userNotification.requestPermissionForPushNotifications()
   return true
 }
}
...

There are 2 types of implementation (explicit and implicit), for its simplicity and to start quickly we will use the implicit implementation of the SDK as well as requesting permissions to the user to receive notifications when opening the application, we will also implement the methods messagingReceivedNotification and messagingInteractionNotification.

Ready!, you can now run your project, accept the permissions to receive notifications and use the push token that APNS assigns you to send notifications using our.

📘

NOTE

Remember to activate the logs in the configuration file indicated in step 2, so you can see in the console the push token that assigns you APNS and copy it easily.

Usage

To make use of the functionalities that Messaging SDK offers, the Messaging class is available, to obtain an instance of this class you can do.

let messaging = Messaging.shared

By doing this you have access to the following:

Messaging.shared.userNotification.requestPermissionForPushNotifications()
Messaging.shared.fetchDevice(forceCallToService:)
Messaging.shared.fetchUser(forceCallToService:)
Messaging.shared.observe\EventName/
Messaging.shared.removeObserve\EventName/

Deep Linking

MessagingLibrary allows for Push Notifications to contain a link to a section inside of the
Application or to a Web Page link.

For this we have 3 modalities:

  1. Explicit behavior using Payload

  2. URL Schema

  3. Universal Links

Payload

To use this modality, indicate the behavior that will occur once the Push Notification is received, in the following way:

...
import MessagingLibrary
@UIApplicationMain
 
class AppDelegate: MessagingAppDelegate {
 ...
 override func messagingReceivedDeepLink(_ notification: MessagingNotification) {
   // desired behavior when receiving a deep link notification.
 }
...
}

messagingReceivedDeepLink is a function that is invoked when a notification of type deeplink is received and is found in MessagingAppDelegate or MessagingUserNotificationDelegate, the idea is to define what to do with the overwriting of this method.

Note: For the execution of this method, the user is required to interact with the Push Notification, so it must be shown on the screen with the messagingReceivedNotification function:

...
 override func messagingReceivedNotification(_ notification: MessagingNotification) -> UNNotificationPresentationOptions {
   if notification.deepLink {         
     return [.alert, .sound] }        
   }
   ...
 }
...

In this example, if a Deep Link Notification is received, it is displayed on the screen.

URL Schema

A linking Scheme allows you to associate a link with your Application.

This approach uses the linking scheme to determine the Application linked to that Scheme.
Once configured, you will have a link that will open your Application and process this link as needed.

To associate a URL Scheme to your Application, open your project settings, enter into the Info tab, and click on the URL types section.

1005

This is an example of a linking scheme:

yourapp://sectionapp?param1=value1&...&paramN=valueN

You can use this link in a Push Notification or Website. Indicate that it is a Deeplink Push Notification and enter the link in an attribute called Schema.
As an option, you may put other parameters of interest since these will be added to the URL when it is being processed.

Example: Website

Once you have configured your project to work with deeplink, you can place these links on a website of interest and if the person who clicks on it has the application installed, it will open the section that the link manages.

...
<a href="yourapp://sectionapp?param1=value1&...&paramN=valueN">
  Open app
</a>
...

Example: Push Notification Data

Once your project is set up to work with deeplink, you can send Deep Link notifications to open the section that the link manages on the device receiving the notification.

{
 "data": {
   "deepLink": true,
   "schema":   "yourapp://sectionapp?param1=value1&...&paramN=valueN", "another1": "value1",
   ...
   "anotherX": "valueX"
 }
}

The following method is used to indicate the behavior that will be done to process the URL:

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
 // when opened using url schema
 return true
}

Now all the information received by the URL can be extracted from the URL object, or if you wish, use another structure like NSURLComponents to support the methods you have and obtain the path or the query parameters.

In this example, we use NSURLComponents to extract the information from the URL and place it in a dictionary:

var urlData:[String: Any?] = [:]
urlData["url.absoluteString"] = url.absoluteString
if let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true){
   urlData["path"] = components.path
   var params:[String: Any?] = [:]
   for param in components.queryItems ?? [] {
       params[param.name] = param.value
   }
   urlData["queryItems"] = params
}

Universal Link

A universal link allows you to associate a domain to your application, once configured you can receive parameters and indicate the desired behavior when pressing this link, if a user tries to open a universal link and has installed an application that works with this link, the application will open and interact as configured in the code.

These are the high level steps to make universal links work for your application:

Set up your application to register the approved domains

  1. Register your application at developers.apple.com

  2. Activate associated domains in your application identifier

  3. Activate partner domains in your Xcode project

  4. Add the appropriate domain authorization

  5. Make sure the authorization file is included in the compilation

Configure your website to host the apple-app-site-association (AASA)

  1. Buy a domain name or choose one you already have

  2. Purchase the SSL certificate for the domain name

  3. Create a structured JSON apple-app-site-association file

  4. Sign the JSON file with the SSL certificate

  5. Configure the file server

For more information you can consult the official apple documentation Supporting Associated Domains

Once you comply with all the configuration requirements you can place in your delegate app the following method.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void, window: UIWindow?) -> Bool {
 if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
   if let url = userActivity.webpageURL {
     // do on received universal link
   }
 }
 return false
}

Example: Website

Once you have configured your project to work with deeplink, you can place these links on a website of interest and if the person who clicks on it has the application installed, it will open the section that the link manages.

...
<a href="https://your-domain?param1=value1&...&paramN=valueN">
  Open app
</a>
...

Example: Push Notification Data

Once your project is set up to work with deeplink, you can send Deep Link notifications to open the section that the link manages on the device receiving the notification.

{
 ...
 "data": {
   "deepLink": true,
   "applink":   "http://your-domain?param1=value1&...&paramN=valueN", "another1": "value1",
   ...
   "anotherX": "valueX"
 }
}

What options do you have to implement MessagingLibrary in your project?

There are 2 ways to implement MessagingLibrary in your project implicitly and explicitly.

Implicit Implementation

It is recommended to use when the definition of your delegate app class does not depend on a third party library. This implementation requires that the parent class of the App Delegate class of your project is MessagingAppDelegate.

Open your AppDelegate import MessagingLibrary module and replace the parent class UIResponder and implementation UIApplicationDelegate with MessagingAppDelegate

import MessagingLibrary
@UIApplicationMain
class AppDelegate: MessagingAppDelegate {      
 // you can leave this empty if you're using a storyboard.
}

📘

NOTE

You can overwrite the MessagingAppDelegate methods in your AppDelegate, but remember to invoke the parent via super.

import MessagingLibrary
@UIApplicationMain
class AppDelegate: MessagingAppDelegate {        
override func application(_ application: UIApplication, didFinishLaunchingWithOptions
  // your code
  return super.application(application, didFinishLaunchingWithOptions: launchOptions)
 }
}

Explicit Implementation

If you cannot do without the current parent class of your project, import the MessagingLibrary module and place the following invocations in the methods that are mentioned in your AppDelegate class.

In the applicationDidFinishLaunchingWithOptions method place MessagingImplementation.initialize(), in this manner:

override func application(_ application: UIApplication, didFinishLaunchingWithOptions la      MessagingImplementation.initialize()
  // your code...
  return true
}

In the applicationDidRegisterForRemoteNotificationsWithDeviceToken method, place MessagingImplementation.indicate(pushToken: deviceToken), in this manner:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
 MessagingImplementation.indicate(pushToken: deviceToken) // it is necessary for the correct functioning of the sdk
}
 
func applicationWillEnterForeground(_ application: UIApplication) {
 MessagingImplementation.checkChanges() // it is necessary for the correct functioning of the sdk
}

Also in method application (:didReceiveRemoteNotification:fetchCompletionHandler) place MessagingImplementation.didReceiveRemoteNotification(:fetchCompletionHandler), this way:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
 MessagingImplementation.didReceiveRemoteNotification(userInfo, fetchCompletionHandler: completionHandler) // it is necessary for the correct functioning of the sdk
}

Finally you can implement the MessagingNotificationDelegate interface in your AppDelegate class to manage what happens when a notification arrives.

...
class AppDelegate: ..., MessagingNotificationDelegate {
 ...
}
...

Getting a MessagingNotification (willPresent)

This way it will process all the notifications that arrive at the device, whether they are in background or foreground, regardless of whether the user interacts with them.

import MessagingLibrary
@UIApplicationMain
class AppDelegate: MessagingAppDelegate or ... MessagingUserNotificationDelegate {
 override func messagingReceivedNotification(_ notification: MessagingNotification) -> UNNotificationPresentationOptions {
   ...
   // your code
   // notification.actionIdentifier // has your custom action identifier
 }
}

Another way to process notifications is through an observer.

import MessagingLibrary
class ExampleViewController: UIViewController {
 ...
 private var ReceivedNotification: MessagingNotification?
 override func viewDidLoad() {
 ...
 _ = Messaging.shared.observeReceivedNotification(self, do: #selector(workWithUser(_:)))
 ...
 }
 // Unlike the previous examples, this case does not require a request for notification since the notification is executed at the moment it is received.
 @objc func workWithNotification( _ notification: Notification){
  if let messagingNotification = notification.object as? MessagingNotification {
   // MessagingNotification availability
   self.ReceivedNotification = messagingNotification
  }
 }
 
 override func viewDidDisappear(_ animated: Bool) {
 ...
 _ = Messaging.shared.removeObserveReceivedNotification(self)
 ...
 }
}

To control the interaction of the notification (didReceive)

This method will only run when the user of the device presses the notification.

import MessagingLibrary
@UIApplicationMain
class AppDelegate: MessagingAppDelegate or ... MessagingUserNotificationDelegate {
 override func messagingInteractionNotification(_ notification: MessagingNotification) {
   ...
   // your code
   // notification.actionIdentifier // has your custom action identifier
 }
}

Getting MessagingDevice

This example shows you how to request information from a device using observers and the fetchDevice method to request information from the library.

import MessagingLibrary
class ExampleViewController: UIViewController {
 ...
 private var device: MessagingDevice?
 
 override func viewDidLoad() {
   ...
   _ = Messaging.shared.observeDeviceFetchResponse(self, do: #selector(workWithDevice(_:)))
   ...
 }
 
 func onAnyEventToGetDevice(){
   Messaging.shared.fetchDevice()
 }
 
 @objc func workWithDevice( _ notification: Notification){
   if let device = notification.object as? MessagingDevice {
     // MessagingDevice availability
     self.device = device
   }
 }
 
 override func viewDidDisappear(_ animated: Bool) {
   ...
   _ = Messaging.shared.removeObserveDeviceFetchResponse(self)
   ...
 }
}

Getting MessagingUser

This example shows you how to request information from a user using observers and the fetchUser method to request information from the library.

import MessagingLibrary
class ExampleViewController: UIViewController {
 ...
 private var user: MessagingUser?
 
 override func viewDidLoad() {
   ...
   _ = Messaging.shared.observeUserFetchResponse(self, do: #selector(workWithUser(_:)))
   ...
 }
 
 func onAnyEventToGetUser(){
   // Need MessagingDevice
   Messaging.shared.fetchUser()
 }
 
 @objc func workWithUser( _ notification: Notification){
   if let user = notification.object as? MessagingUser {
     // MessagingUser availability
     self.user = user
   }
 }
 
 override func viewDidDisappear(_ animated: Bool) {
   ...
   _ = Messaging.shared.removeObserveUserFetchResponse(self)
   ...
 }
}