iOS Basic Integration

SDK Stats

Current Version: v0.33.0

Open Source Github Repo: https://github.com/BranchMetrics/ios-branch-deep-linking

SDK Size: ~220kb (with all Branch features enabled)

Speed: Median 80ms to 250ms

Minimum XCode Version: 11+

Inconsistent Universal links behavior on iOS 11.2+

After updating a device to iOS 11.2+, we found that the app's AASA file is no longer downloaded reliably onto your user’s device after an app install. As a result, clicking on Universal Links will no longer open the app consistently. You can set forced uri redirect mode on your Branch links to open the app with URI schemes. View details of the issue on the Apple Bug report.

Configure Branch

image

Configure Bundle Identifier

image

Configure Associated Domains

  • Add your link domains from your Branch Dashboard
  • -alternate is needed to ensure proper functioning of Universal Links & Deep Views for users that do not have your app installed.
  • test- is needed if you need use a test key
  • If you use a custom link domain, you will need to include your old link domain, your -alternate link domain, and your new link domain

image

Add CTD for Universal Email

In order for Branch links to open the app directly on iOS, you must add your ESP’s CTD to your Associated Domains entitlement. This allows Apple to recognize the click tracking domain as a Universal Link, opening the app immediately without the browser opening.

  1. In Xcode, go to the Capabilities tab of your project file.
  2. Scroll down and enable Associated Domains if it is not already enabled.

    image

  3. Copy your click tracking domain from the email you received from Branch, or retrieve it from your ESP's settings.

  4. In the Domains section, click the + icon and add your click tracking domain. For example, if your click tracking domain is email.example.com, add an entry for applinks:email.example.com.

    image

Configure Entitlements

  • Confirm entitlements are within target (This file is configured automatically when completing the steps above in Capabilities tab of Xcode)

image

Configure Info.plist

  • Add Branch Dashboard values

    • Add branch_universal_link_domains with your live key domain
    • Add branch_key with your current Branch key
    • Add your URI scheme as URL Types -> Item 0 -> URL Schemes

Confirm App Prefix

Install Branch

Option 1

CocoaPods

platform :ios, '8.0'

target 'APP_NAME' do
  # if swift
  use_frameworks!

  pod 'Branch'
end
pod install && pod update

iAd Support Included by Default

With the release of v0.28.0, the Branch SDK for iOS now includes all of the necessary dependencies for iAD when installed via CocoaPods.

Option 2

Carthage

 github "BranchMetrics/ios-branch-deep-linking"
  • Import AdSupport, SafariServices, MobileCoreServices, CoreSpotlight, Webkit and iAd into Linked Frameworks

Option 3

Manually install the source code with dependencies

  • Drag and drop Branch.framework into Embedded Binaries (select Copy items if needed)
  • Import AdSupport, SafariServices, MobileCoreServices, CoreSpotlight, Webkit and iAd into Linked Frameworks

image

Initialize Branch

Apps not Using Scenes

import UIKit
import Branch

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // if you are using the TEST key
  Branch.setUseTestBranchKey(true)
  // listener for Branch Deep Link data
  Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
       // do stuff with deep link data (nav to page, display content, etc)
      print(params as? [String: AnyObject] ?? {})
  }
  return true
}

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    return Branch.getInstance().application(app, open: url, options: options)
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
  // handler for Universal Links
    return Branch.getInstance().continue(userActivity)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // handler for Push Notifications
  Branch.getInstance().handlePushNotification(userInfo)
}
import UIKit
import Branch

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // if you are using the TEST key
  Branch.setUseTestBranchKey(true)
  // listener for Branch Deep Link data
  Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
    // do stuff with deep link data (nav to page, display content, etc)
    print(params as? [String: AnyObject] ?? {})
  }
  return true
}

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  Branch.getInstance().application(app, open: url, options: options)
  return true
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
  // handler for Universal Links
  Branch.getInstance().continue(userActivity)
  return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // handler for Push Notifications
  Branch.getInstance().handlePushNotification(userInfo)
}
#import "AppDelegate.h"
#import "Branch/Branch.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // if you are using the TEST key
  [Branch setUseTestBranchKey:YES];
  // listener for Branch Deep Link data
  [[Branch getInstance] initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary * _Nonnull params, NSError * _Nullable error) {
    // do stuff with deep link data (nav to page, display content, etc)
    NSLog(@"%@", params);
  }];
  return YES;
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  [[Branch getInstance] application:app openURL:url options:options];
  return YES;
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
  // handler for Universal Links
  [[Branch getInstance] continueUserActivity:userActivity];
  return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
  // handler for Push Notifications
  [[Branch getInstance] handlePushNotification:userInfo];
}

@end

Apps Using Scenes

Using iOS Scenes

If your app uses iOS Scenes, please use the code samples below.

  • In your app's AppDelegate file:
import UIKit
import Branch

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {



  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
      // Override point for customization after application launch.

              // This version of initSession includes the source UIScene in the callback
        BranchScene.shared().initSession(launchOptions: launchOptions, registerDeepLinkHandler: { (params, error, scene) in
            
        })
      return true
  }

  func applicationWillTerminate(_ application: UIApplication) {
      // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
  }

  // MARK: UISceneSession Lifecycle

  func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
      // Called when a new scene session is being created.
      // Use this method to select a configuration to create the new scene with.
      return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
  }

  func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
      // Called when the user discards a scene session.
      // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
      // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  }
}
#import "AppDelegate.h"
@import Branch;

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    [[BranchScene shared] initSessionWithLaunchOptions:launchOptions registerDeepLinkHandler:^(NSDictionary * _Nullable params, NSError * _Nullable error, UIScene * _Nullable scene) {
        
    }];

    return YES;
}


- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


#pragma mark - UISceneSession lifecycle


- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}


- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

@end
  • In your app's SceneDelegate file:
import UIKit
import Branch
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var window: UIWindow?
  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
      // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
      // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
      // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
      guard let _ = (scene as? UIWindowScene) else { return }
              // workaround for SceneDelegate continueUserActivity not getting called on cold start
        if let userActivity = connectionOptions.userActivities.first {
            
            BranchScene.shared().scene(scene, continue: userActivity)
        }
  }
  func sceneDidDisconnect(_ scene: UIScene) {
      // Called as the scene is being released by the system.
      // This occurs shortly after the scene enters the background, or when its session is discarded.
      // Release any resources associated with this scene that can be re-created the next time the scene connects.
      // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
  }
  func sceneDidBecomeActive(_ scene: UIScene) {
      // Called when the scene has moved from an inactive state to an active state.
      // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
  }
  func sceneWillResignActive(_ scene: UIScene) {
      // Called when the scene will move from an active state to an inactive state.
      // This may occur due to temporary interruptions (ex. an incoming phone call).
  }
  func sceneWillEnterForeground(_ scene: UIScene) {
      // Called as the scene transitions from the background to the foreground.
      // Use this method to undo the changes made on entering the background.
  }
  func sceneDidEnterBackground(_ scene: UIScene) {
      // Called as the scene transitions from the foreground to the background.
      // Use this method to save data, release shared resources, and store enough scene-specific state information
      // to restore the scene back to its current state.
  }
  func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        BranchScene.shared().scene(scene, continue: userActivity)
  }
  func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        BranchScene.shared().scene(scene, openURLContexts: URLContexts)
  }
}
#import "SceneDelegate.h"
@import Branch;
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    // workaround for SceneDelegate continueUserActivity not getting called on cold start
    NSUserActivity *activity = [[connectionOptions userActivities] allObjects].firstObject;
    if (activity) {
        [[BranchScene shared] scene:scene continueUserActivity:activity];
    }
}
- (void)sceneDidDisconnect:(UIScene *)scene {
    // Called as the scene is being released by the system.
    // This occurs shortly after the scene enters the background, or when its session is discarded.
    // Release any resources associated with this scene that can be re-created the next time the scene connects.
    // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
    // Called when the scene has moved from an inactive state to an active state.
    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
- (void)sceneWillResignActive:(UIScene *)scene {
    // Called when the scene will move from an active state to an inactive state.
    // This may occur due to temporary interruptions (ex. an incoming phone call).
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
    // Called as the scene transitions from the background to the foreground.
    // Use this method to undo the changes made on entering the background.
}
- (void)sceneDidEnterBackground:(UIScene *)scene {
    // Called as the scene transitions from the foreground to the background.
    // Use this method to save data, release shared resources, and store enough scene-specific state information
    // to restore the scene back to its current state.
}
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
    [[BranchScene shared] scene:scene continueUserActivity:userActivity];
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    [[BranchScene shared] scene:scene openURLContexts:URLContexts];
}
@end

Track Users

  • Sets the identity of a user (email, ID, UUID, etc) for events, deep links, and referrals

Invoke setIdentity after initSession

initSession must be invoked first, otherwise the initSession callback will not fire properly.

// login
Branch.getInstance().setIdentity("your_user_id")

// logout
Branch.getInstance().logout()
// login
[[Branch getInstance] setIdentity:@"your_user_id"];

// logout
[[Branch getInstance] logout];

Updated 18 days ago

iOS Basic Integration


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.