Iterable's iOS SDK supports features such as push notifications, in-app messages, deep links, and Mobile Inbox. This article describes how to install and configure the SDK to work with Iterable.
In this article
To install and configure Iterable's iOS SDK, follow these steps:
- Supported iOS versions
- Encrypted data
-
Installation steps
- Step 1: Create a Notification Service Extension (if necessary)
- Step 2: Install the SDK
- Step 3: Configure the Notification Service Extension (if necessary)
- Step 4: Import IterableSDK wherever necessary
- Step 5: Create a mobile API key
- Step 6: Initialize the SDK with your API key
- Step 7: Enable push notifications
- Step 8: Enable in-app messages
- Step 9: Verify that the SDK can communicate with Iterable
- Embedded Messaging
- Upgrading the SDK
- Further reading
Supported iOS versions
Iterable's iOS SDK supports iOS 10 and higher.
Encrypted data
Iterable's iOS SDK encrypts some data at rest. For more information, read Upgrading to 6.4.8+.
Installation steps
Follow these steps to install the SDK. If you're upgrading from a previous version, also see Upgrading the SDK.
Step 1: Create a Notification Service Extension (if necessary)
For an iOS app to support push notifications that contain action buttons, images, videos or custom sounds, its Xcode project must contain a Notification Service Extension. It's helpful to set your app's Notification Service Extension target up before installing and configuring the SDK.
To add a Notification Service Extension target to your Xcode project:
Open your app's Xcode project.
Choose File > New > Target.
-
On the iOS tab, select Notification Service Extension:
Click Next.
Provide all necessary configuration information for the Notification Service Extension.
Click Finish.
Next, install the SDK using one of the methods described below. Then, configure the Notification Service Extension
Step 2: Install the SDK
To install the SDK, use the Swift Package Manager, CocoaPods, Carthage, or install it manually.
IMPORTANT
Starting with version 6.4.0
,
Iterable's iOS SDK no longer supports iOS 9. For iOS 9 support, use version
6.3.4
.
Step 2.1: Install the SDK with the Swift Package Manager
Swift Package Manager is an Xcode tool that installs project dependencies. To use it to install Iterable's iOS SDK, follow these steps:
NOTES
The Swift Package Manager can install versions 6.2.0 and higher of Iterable's iOS SDK.
In Xcode, click File > Add Packages....
-
In the window that opens, enter
https://github.com/Iterable/iterable-swift-sdk
in the upper-right corner: -
Use the Dependency Rule and Add to Project options to specify which version of the SDK you'd like to add, and the project to which you'd like to add it. For example, to use the latest version of the SDK found the current major version sequence, choose Up to Next Major Version for Dependency Rule and enter
6.0.0
for the lower version number.For more information about these options, see the Decide on Package Requirements section of Apple's guide, Adding Package Dependencies to Your App.
Click Add Package.
-
When prompted to choose package products:
Check IterableSDK, and choose the target associated with your app.
If you'll send push notifications with action buttons, images, videos, or custom sounds, check IterableAppExtensions. Then, choose the target associated with your app's Notification Service Extension.
Click Add Package.
The packages will be added to your app.
Step 2.2: Install the SDK with CocoaPods
To use CocoaPods to install Iterable's iOS SDK, follow these steps:
-
If your project does not yet have a
Podfile
, create one:In the terminal, navigate to the directory containing your project's .xcodeproj file.
Run this command:
pod init
.
-
Edit the
Podfile
:In this file, add the
Iterable-iOS-SDK
pod to your project's app target.If you will send push notifications that contain action buttons, images, videos or custom sounds, add the
Iterable-iOS-AppExtensions
pod to your project's Notification Service Extension.-
After these changes, your
Podfile
should look similar to this:platform :ios, '11.0' target '<YOUR_APP_TARGET>' do pod 'Iterable-iOS-SDK' end target '<YOUR_NOTIFICATION_EXTENSION_TARGET>' do pod 'Iterable-iOS-AppExtensions' end
NOTE
In versions 6.3.3 and above of Iterable's iOS SDK, it's no longer necessary to include
use_frameworks!
in yourPodfile
.
In the terminal, run
pod install
to install the pods you configured in the previous step. If you see errors, trypod install --repo-update
(docs).Your project now has an .xcworkspace file. Use this file to open your project, instead of its
.xcodeproj
file.
For more information, read the CocoaPods documentation.
Step 2.3: Install the SDK with Carthage
To use Carthage to install Iterable's iOS SDK, follow these steps:
Step 2.3.1: Add IterableSDK.framework
First, add IterableSDK.framework
to your project:
Create a
Cartfile
in the same directory as your .xcodeproj or .xcworkspace file.-
Add this line to the
Cartfile
:github "Iterable/swift-sdk"
Open a terminal window. In it, navigate to the same directory as your
Cartfile
.Run this command:
carthage update
.From the terminal, open a Finder window:
open .
. In this window, navigate to theCarthage/Build/iOS
subdirectory. Keep this window open.Open your app's Xcode project.
From the Finder window opened above, drag
IterableSDK.framework
onto Xcode's Project Navigator (far left column). When prompted, add the framework to your app target.In Xcode's Project Navigator, select the top item, which corresponds to the project itself.
Under Targets, select your app.
Navigate to Build Phases.
Add a build phase by clicking + and selecting New Run Script Phase. A Run Script section will appear.
-
In the new Run Script section, add this command in the text area:
/usr/local/bin/carthage copy-frameworks
-
In the Input Files section, click + and add:
$(SRCROOT)/Carthage/Build/iOS/IterableSDK.framework
-
In the Output Files section, add the path to the copied framework:
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/IterableSDK.framework
Step 2.3.2: Add IterableAppExtensions.framework
If you will send push notifications that have action buttons, images, videos or custom sounds, follow these steps, too:
Open your app's Xcode project.
From the Finder window opened in the previous section, drag
IterableAppExtensions.framework
onto Xcode's Project Navigator (far left column). When prompted, add the framework to your Notification Service Extension target.In Xcode's Project Navigator, select the top item, which corresponds to the project itself.
Under Targets, select your Notification Service Extension.
Navigate to Build Phases.
Add a build phase by clicking + and selecting New Run Script Phase. A Run Script section will appear.
-
In the new Run Script section, in the script text area, add this command:
/usr/local/bin/carthage copy-frameworks
-
In the Input Files section, click + and add this path:
$(SRCROOT)/Carthage/Build/iOS/IterableAppExtensions.framework
-
In the Output Files section, add the path to the copied framework:
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/IterableAppExtensions.framework
Step 3: Configure the Notification Service Extension (if necessary)
If you added a Notification Service Extension to your project (above),
set it up to handle media attachments and action buttons. To do this, use the
ITBNotificationServiceExtension
class provided by Iterable's iOS SDK:
Open the
NotificationService
class (auto-generated by Xcode when you added the Notification Service Extension to your project).-
For Swift-based projects:
Add an import:
import IterableAppExtensions
.-
Update
NotificationService
so that it extendsITBNotificationServiceExtension
, and contains no other code:import UserNotifications import IterableAppExtensions class NotificationService: ITBNotificationServiceExtension { }
IMPORTANT
If you're using React Native, you may need to install some Objective-C compatibility headers and use different import statements. For more information, read Installing Iterable's React Native SDK — Step 3.3: Import the SDK.
-
For Objective-C projects:
Add an import:
@import IterableAppExtensions;
.-
Configure the class so that it's similar to the following:
// File: NotificationService.m #import "NotificationService.h" @import IterableAppExtensions; @interface NotificationService () @property (nonatomic, strong) ITBNotificationServiceExtension *baseExtension; @end @implementation NotificationService - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.baseExtension = [[ITBNotificationServiceExtension alloc] init]; [self.baseExtension didReceiveNotificationRequest:request withContentHandler:contentHandler]; } - (void)serviceExtensionTimeWillExpire { [self.baseExtension serviceExtensionTimeWillExpire]; } @end
Step 4: Import IterableSDK wherever necessary
To use Iterable's iOS SDK in your app's code, import it at the top of any Swift or Objective-C files that reference it. For example:
Swift
// In AppDelegate.swift and any other file where you're using IterableSDK import IterableSDK
Objective-C
// In AppDelegate.m and any other file where you're using IterableSDK @import IterableSDK;
IMPORTANT
If you're using React Native, you may need to install some Objective-C compatibility headers and use different import statements. For more information, read Installing Iterable's React Native SDK — Step 3.3: Import the SDK.
Step 5: Create a mobile API key
To make calls to Iterable's's API, the SDK needs a mobile API key. To learn how to create one, read API Keys
WARNING
Never embed server-side API keys in client-side code (whether JavaScript, a mobile application or otherwise), since they can be used to access all of your project's data. For a mobile app, use a mobile API key (if possible, we recommend using JWT authentication for additional security).
If necessary, use different API keys for debug and production builds.
Step 6: Initialize the SDK with your API key
Next, you'll need to make a few updates in your app delegate's
application(_:didFinishLaunchingWithOptions:)
method:
IterableAPI.initialize
Step 6.1: Call Call initialize(apiKey:launchOptions:config:)
, passing your Iterable API key
as a parameter:
Swift
let config = IterableConfig() IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config: config)
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" config:config]
IterableConfig
provides configuration and customization options for the
Iterable SDK. You'll use it later to set up push notifications and in-app
messages.
Step 6.2: If necessary, configure the SDK to use Iterable's EDC
If your project is hosted on Iterable's European data center (EDC), configure the SDK to use Iterable's EDC-based endpoints:
Swift
let config = IterableConfig() config.dataRegion = IterableDataRegion.EU IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions: launchOptions, config: config)
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; config.dataRegion = IterableDataRegion.EU [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" launchOptions:launchOptions config:config]
allowedProtocols
field
Step 6.3: Set the Starting with version 6.4.0
of Iterable's iOS SDK, you'll need to declare the specific URL protocols that the
SDK can expect to see on incoming links (and that it should handle as needed). This
prevents the SDK from opening links that use unexpected URL protocols.
To do this, set the allowedProtocols
field (on the IterableConfig
object you
pass to the SDK's initialize
method) to an array that contains the protocols you'd
like the SDK to support.
For example, this code allows the SDK to handle http://
, tel://
, and custom://
links:
Swift
let config = IterableConfig() config.allowedProtocols = ["http", "tel", "custom"] IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config)
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; config.allowedProtocols = @["http", "tel", "custom"]; [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" launchOptions:launchOptions, config:config]
IMPORTANT
Iterable's iOS SDK handles https
, action
, itbl
, and iterable
links,
regardless of the contents of this array. However, you must explicitly declare any
other types of URL protocols you'd like the SDK to handle (otherwise, the SDK
won't open them in the web browser or as deep links).
Step 6.4: Set up a push integration
In Iterable, you'll create logical mobile apps to store information about your real mobile apps—including information about the configuration parameters Iterable needs to send push notifications to them. Iterable refers to these push notification configuration parameters as push integrations.
TIP
Older push integrations may not yet be associated in Iterable with a mobile app. However, you can assign them.
By default, the SDK expects your push integration's name to match your app's bundle ID. However, if your Iterable push integration was created before August 2019, it may have a custom name. To handle this, do one of the following things:
In Iterable, assign the existing push integration to a mobile app. If you do this, the SDK will use the push integration that matches your mobile app's bundle ID.
-
Alternatively, specify the custom push integration name when initializing the SDK:
Swift
let config = IterableConfig() config.pushIntegrationName = "<PUSH_INTEGRATION_NAME>" IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config)
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; config.pushIntegrationName = @"<PUSH_INTEGRATION_NAME>"; [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" launchOptions:launchOptions, config:config]
TIP
To find the name of your push integration, navigate in Iterable to Settings > Apps and websites, open the mobile app that's associated with your actual app, look at the Details section, and find the Package Name.
Step 6.5: Choose whether or not to use in-memory storage for in-app messages
By default, Iterable's iOS SDK stores in-app messages in an unencrypted local
file. To instead store in-app messages in memory, set useInMemoryStorageForInApps
to true
:
Swift
let config = IterableConfig() config.useInMemoryStorageForInApps = true IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config)
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; config.useInMemoryStorageForInApps = YES; [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" launchOptions:launchOptions, config:config];
For more information, read Upgrading to 6.4.9+.
Step 6.6: Handle JWT-enabled API keys
If you're using a JWT-enabled API Key, you'll need custom code to manage JWT tokens for the signed-in user.
Step 6.6.1: Register an auth handler
When initializing the SDK, provide an auth handler. The SDK uses the auth handler to:
- Fetch new JWT tokens from your server.
- Report when a non-null JWT token has been retrieved.
- Report when there have been failures fetching new JWT tokens.
The object that you pass to the SDK as an auth manager must implement the
IterableAuthDelegate
protocol:
@objc public protocol IterableAuthDelegate: AnyObject { @objc func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) @objc func onAuthFailure(_ authFailure: AuthFailure) }
For example, you might user your AppDelegate
as your IterableAuthDelgate
:
extension AppDelegate: IterableAuthDelegate { // ... func onAuthTokenRequested(completion: @escaping AuthTokenRetrievalHandler) { // Fetch a JWT token for the signed-in user, from your server, and // return it to the SDK. completion("<JWT_TOKEN_FOR_THE_CURRENT_USER>") } func onAuthFailure(_ authFailure: AuthFailure) { // Inspect the authFailure enum case and take any necessary action. For // example, you can pause auth retries (see section 5.5.3, below). } // ... } // Then, when initializing the SDK... let config = IterableConfig() config.authDelegate = self IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config)
IMPORTANT
You'll need to keep a strong reference to your IterableAuthDelegate
instance.
IterableConfig
only holds a weak reference to it.
onAuthTokenRequested
The SDK calls onAuthTokenRequested
when it needs a new JWT token for the
signed-in user. This method should fetch a new JWT token from your server and
return it to the SDK as a string.
This method is called when:
- You identify a user by calling
setEmail
orsetUserId
. - You update a user's email address by calling
updateEmail
. - The current JWT token has expired, or is about to expire.
- The SDK receives a JWT-related
401
response from Iterable's API.
onAuthFailure
The SDK calls onAuthFailure
after it fails to fetch a new JWT token for the
signed-in user. The AuthFailure
object passed to this method describes the
reason for the failure, along with other information.
This method is called when:
-
onAuthTokenRequested
returnsnull
. -
onAuthTokenRequested
throws an exception. - The SDK receives a JWT-related
401
response from Iterable's API. - The token returned by
onAuthTokenRequested
is invalid.
In onAuthFailure
, to determine the reason for the failure, inspect the
AuthFailure
object, which has these properties:
-
userKey
- A string that identifies the user byuserId
oremail
. -
failedAuthToken
- The JWT token that caused the failure. -
failedRequestTime
- The timestamp of the failed request, if applicable. -
failureReason
- AnAuthFailureReason
enum case that indicates the reason for the failure.
AuthFailureReason
can be:
-
authTokenExpirationInvalid
– An auth token's expiration must be less than one year from its issued-at time. -
authTokenExpired
– The token has expired. -
authTokenFormatInvalid
– Token has an invalid format (failed a regular expression check). -
authTokenGenerationError
–onAuthTokenRequested
threw an exception. -
authTokenGenericError
– Any other error not captured by another constant. -
authTokenInvalidated
– Iterable has invalidated this token and it cannot be used. -
authTokenNull
–onAuthTokenRequested
returned a null JWT token. -
authTokenPayloadInvalid
– Iterable could not decode the token's payload (iat
,exp
,email
, oruserId
). -
authTokenSignatureInvalid
– Iterable could not validate the token's authenticity. -
authTokenUserKeyInvalid
– The token doesn't include anemail
or auserId
. Or, one of these values is included, but it references a user that isn't in the Iterable project. -
authTokenMissing
– The request to Iterable's API did not include a JWT authorization header.
TIP
You can also provide a JWT token for the current user by passing it directly to
setEmail
or setUserId
.
Step 6.6.2: Set an expiring token refresh period
To specify how long before the expiration of the user's current JWT token
the SDK should call your auth token refresh handler,
to fetch a new token, set expiringAuthTokenRefreshPeriod
on IterableConfig
:
let config = IterableConfig() // ... other configuration options ... config.expiringAuthTokenRefreshPeriod = 45.0 IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config)
Step 6.6.3: Set an auth retry policy
To control how the SDK handles consecutive JWT token refresh attempts, specify an auth retry policy. An auth retry policy allows you to control:
- The number of consecutive times the SDK should attempt to refresh a user's JWT token, in between successful API calls, before giving up.
- The interval between those attempts.
- A backoff strategy.
// When creating a RetryPolicy object, specify a maximum number of retries, an // interval between retries, and a backoff strategy: .linear or .exponential. // The SDK's default RetryPolicy has a maximum of 10 retries, an interval of 6 // seconds, and a linear backoff strategy. let config = IterableConfig() // ... other configuration options ... config.retryPolicy = RetryPolicy(maxRetry: 10, retryInterval: 5, retryBackoff: .linear) IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", config: config)
After the SDK reaches the maximum number of consecutive JWT-related request
failures, as configured by your RetryPolicy
, it stops attempting to refresh
the JWT token.
It's also possible to manually pause JWT token refresh attempts. To do this, call:
IterableAPI.pauseAuthRetries(true) // or false
When JWT refresh attempts have been paused, they'll only resume after:
- You provide a new JWT token to the SDK, by calling
setAuthToken
. - You identify the user by setting
setEmail
orsetUserId
. - You update the user's email by calling
updateEmail
. - The app restarts.
- You manually pause and unpause JWT token refresh attempts, by calling:
// If you didn't manually pause JWT refresh attempts in the first place, // first pause the retries, and then unpause them. IterableAPI.pauseAuthRetries(true) IterableAPI.pauseAuthRetries(false)
Step 7: Enable push notifications
IMPORTANT
Iterable sends push notifications to iOS apps for two reasons:
- When you send push notification campaigns
- Silently, to tell the app to download new in-app messages
Because Iterable uses silent push notifications to help deliver in-app messages, configure your app to support push notifications even if you do not plan to send push notification campaigns.
To enable push notifications, follow the steps described below.
Step 7.1: Set up iOS push notifications in Iterable
Follow the instructions in Iterable's Setting up iOS Push Notifications guide. This document describes how to configure your iOS app's App ID to use push notifications, and how to set up a mobile app (and associated push integration) in Iterable's web app.
Step 7.2: Add the Push Notifications capability to your app
Follow Apple's instructions to add the Push Notifications capability to your app.
If you'll be sending Time Sensitive push notifications (introduced in iOS 15), also add the Time Sensitive Notifications capability. For more information about Time Sensitive notifications, check out this WWDC 2021 talk.
Step 7.3: Enable the Remote Notifications background mode
Follow Apple's instructions to enable the Remote Notifications background mode in your app.
Step 7.4: Fetch a device token from Apple and register it with Iterable
For Iterable to send push notifications to an iOS device, it must know the unique token assigned to that device by Apple.
By default, Iterable's SDK automatically fetches this token from Apple when the
application's code sets IterableAPI.email
or IterableAPI.userId
(which also
disables the device token for the previous email
or userId
, preventing Iterable
from sending push notifications to that user on that device). To fetch the token,
the SDK calls registerForRemoteNotifications()
on UIApplication
.
NOTES
If you set IterableConfig.autoPushRegistration
to false
, the SDK does not
automatically register for a device token. In this case:
- Call
registerForRemoteNotifications()
to register for a token when necessary. - To manually disable push notifications for the current user, call
IterableAPI.disableDeviceForCurrentUser()
.
After fetching a device token, iOS passes it to the application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
method on the app delegate. Configure this method to register the token with
Iterable's SDK, which saves it the user's Iterable profile:
Swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { IterableAPI.register(token: deviceToken) }
Objective-C
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [IterableAPI registerToken:deviceToken]; }
Step 7.5: Handle incoming push notifications and enable push notification tracking
To handle incoming push notifications, and to allow Iterable to track events when a user interacts with push notifications, follow these steps:
-
For some object in your app, conform to the
UNUserNotificationCenterDelegate
protocol (apps commonly use the app delegate for this purpose). Import theUserNotifications
framework, indicate that the class conforms to the protocol, and implement these methods:-
userNotificationCenter(_:willPresent:withCompletionHandler:)
This method can be used to allow your app to display incoming push notifications when it is in the foreground.
-
userNotificationCenter(_:didReceive:withCompletionHandler:)
iOS calls this method when a user interacts with a push notification. From here, Iterable's SDK can create events associated with these interactions.
-
Set this object as the delegate for the current
UNUserNotificationCenter
.
For example, Iterable's Swift and Objective-C sample projects have app delegate code similar to the following:
Swift
class AppDelegate: UIResponder, UIApplicationDelegate { func application(_: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // ... UNUserNotificationCenter.current().delegate = self // ... } // ... } extension AppDelegate: UNUserNotificationCenterDelegate { public func userNotificationCenter(_: UNUserNotificationCenter, willPresent _: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.badge, .banner, .list, .sound]) } public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { IterableAppIntegration.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler) } }
Objective-C
@implementation AppDelegate // In its .h file, the AppDelegate class declares that it conforms to UNUserNotificationCenterDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ... UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; // ... } ##pragma mark - UNUserNotificationCenterDelegate - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionBanner | UNNotificationPresentationOptionList | UNNotificationPresentationOptionSound); } - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { [IterableAppIntegration userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler]; } @end
NOTES
To learn more about push notifications on iOS, read Apple's documentation about the UserNotifications framework.
Step 7.6: (Optional) Request authorization to display push notifications
IMPORTANT
Complete the steps in this section if you plan to use Iterable to send push notification campaigns to your app. Otherwise, they are unnecessary.
iOS apps must have explicit user permission to display push notification alerts, play push notification sounds or update icon badges based on push notifications.
To request this permission, display a prompt by calling the requestAuthorization(options:completionHandler:)
method on UNUserNotificationCenter
.
This is usually done from somewhere in the app delegate. For example:
Swift
UNUserNotificationCenter.current().requestAuthorization(options:[.alert, .badge, .sound]) { (success, error) in if success == true { // ... } }
Objective-C
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ // ... }); } }];
TIP
To learn more about asking for permission to display notifications, read Apple's Asking Permission to Use Notifications guide.
Step 8: Enable in-app messages
To enable in-app messages, follow these steps:
-
Iterable uses silent push notifications to notify an app about new in-app messages awaiting delivery. Because of this, enable push notifications even if you don't plan to send push notification campaigns.
-
Let Iterable's SDK know when the app receives a push notification. This way, it knows to go fetch waiting in-app messages.
To do this, implement the app delegate's
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
method. In it, call the identically named method onIterableAppIntegration
. For example:Swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { IterableAppIntegration.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler) }
Objective-C
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { [IterableAppIntegration application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; }
TIP
You can also use this method to handle silent push notifications, inspecting their payload and kicking off any necessary actions.
Step 9: Verify that the SDK can communicate with Iterable
To test that your app can communicate with Iterable:
-
In your app's code, after initializing the SDK with your API key, set
IterableAPI.email
to a specific email address:Swift
let config = IterableConfig() IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config) IterableAPI.email = "user@example.com"
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" launchOptions:launchOptions, config:config] IterableAPI.email = @"user@example.com";
-
Run the app on a physical device (not the simulator).
Registering for a push notification token from Apple can only be done on a physical device.
-
Check to make sure the new user is visible in Iterable:
Open the Iterable project associated with the API key used in your app's code.
Navigate to Audience > Contact Lookup.
Enter the email address used above and click Search Users.
The user's profile should appear.
If you're having trouble, make sure that you have:
Embedded Messaging
To learn how to use Iterable's iOS SDK with Embedded Messaging, read Embedded Messages with Iterable's iOS SDK.
Upgrading the SDK
This section describes how to upgrade from earlier versions of Iterable's iOS SDK.
Upgrading to 6.5.5+
Version 6.5.5 of Iterable's iOS SDK provides more insight into JWT refresh failures, so you can take appropriate action in your application code.
-
When a JWT refresh fails (for any of various reasons), the SDK calls
onAuthFailure(_ authFailure: AuthFailure)
on theIterableAuthDelegate
instance you provided to the SDK at initialization. TheAuthFailure
object provides more information about the failure.Note that
onAuthFailure(_ authFailure: AuthFailure)
replacesonTokenRegistrationFailed(_ reason: String?)
. If you've implementedonTokenRegistrationFailed
, you'll need to update your application code. -
To set a retry policy for JWT refreshes, you can set the
retryPolicy
property onIterableConfig
to aRetryPolicy
object. Use this object to specify:- The maximum number of consecutive JWT-related request failures the SDK should allow before giving up, Defaults to 10.
- The interval between each JWT refresh attempt. Defaults to 6 seconds.
- A backoff strategy: linear or exponential. Defaults to linear.
You manually pause JWT refresh attempts by calling
IterableAPI.pauseAuthRetries(true)
For more information, see Step 6.6.1: Register an auth handler.
Upgrading to 6.4.9+
Version 6.4.9 of Iterable's iOS SDK makes it possible to store in-app messages in memory, rather than in an unencrypted local file. However, an unencrypted local file is still the default option.
To store in-app messages in memory, set useInMemoryStorageForInApps
to true
:
Swift
let config = IterableConfig() config.useInMemoryStorageForInApps = true IterableAPI.initialize(apiKey: "<YOUR_API_KEY>", launchOptions:launchOptions, config:config)
Objective-C
IterableConfig *config = [[IterableConfig alloc] init]; config.useInMemoryStorageForInApps = YES; [IterableAPI initializeWithApiKey:@"<YOUR_API_KEY>" launchOptions:launchOptions, config:config];
When users upgrade to a version of your iOS app that uses this version of the SDK (or higher), and you've enabled this option, the local file used for in-app message storage (if it already exists) is deleted. However, no data is lost.
Upgrading to 6.4.8+
Starting with version 6.4.8, Iterable's iOS SDK, as a privacy enhancement, encrypts the following data when storing it at rest:
-
email
— The user's email address. -
userId
— The user's ID. -
authToken
— The JWT used to authenticate the user with Iterable's API. -
lastPushPayload
— The JSON payload that came along with the last push notification received by the app.
(Note that Iterable's iOS SDK does not store in-app messages at rest—before or after this update.)
NOTE
Iterable's iOS SDK does, in fact, store in-app messages in an unencrypted local file. However, version 6.4.9 provides an option to store them in memory, instead.
When a user upgrades to a version of your app that uses this version of the SDK (or higher), these fields are encrypted. No data that's already stored is lost.
For more information about the encryption described above, examine the SDK source code:
Upgrading to 6.4.0+
Starting with version 6.4.0
of Iterable's iOS SDK, you'll need to declare the URL protocols that the SDK
should expect to see on incoming links (and then handle as needed). For more
information, read Set the allowedProtocols
field.
Upgrading from a version prior to 6.1.0
Versions 6.1.0+ of the SDK require Xcode 10.2 or higher.
-
In-app messages
-
spawnInAppNotification
The
spawnInAppNotification
method is no longer needed, and will fail to compile. The SDK now displays in-app messages automatically. There is no need to poll the server for new messages. -
Handling manually
To manually control when in-app messages display, set
IterableConfig.inAppDelegate
(anIterableInAppDelegate
object). From itsonNew
method, return.skip
.To get the queue of available in-app messages, call
IterableApi.inAppManager.getMessages()
. Then, callIterableApi.inAppManager.show(message)
to show a specific message. -
Custom actions
The SDK now reserves the
iterable://
URL scheme for Iterable-defined actions handled by the SDK, and theaction://
URL scheme for custom actions handled by the mobile application's custom action handler.If you are currently using the
itbl://
URL scheme for custom actions, the SDK will still pass these actions to the custom action handler. However, support for this URL scheme will eventually be removed (timeline TBD), so it is best to move to theaction://
URL scheme as you can.
-
-
Consolidated deep link URL handling
By default, the SDK handles deep links using the URL delegate assigned to
IterableConfig
.
Further reading
- Identifying the User
- Updating User Profiles
- Tracking Events with Iterable's Mobile SDKs
- Setting up iOS Push Notifications
- Advanced iOS Push Notifications
- In-App Messages on iOS
- Setting up Mobile Inbox on iOS
- Customizing Mobile Inbox on iOS
- iOS Universal Links
- Deep Links in Push Notifications
- Sample apps that use Iterable's iOS SDK
- Configuring Deep Links for Email or SMS
- JWT-Enabled API Keys