iOS 基本集成

👍

SDK 统计

CocoapodsCocoapods

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

SDK 大小:〜220kb(启用了所有 Branch 功能)

速度 :中值80ms至250ms

XCode 最低版本 :12.3+

操作系统最低版本 :iOS 9+

📘

iOS 14 实施

为了帮助您全面管理用户体验,Branch SDK 将不会触发 IDFA 许可弹窗。

然而,如果您选择触发这一弹窗,在可行的情况下,Branch 仍然可以收集并使用 IDFA。

了解更多

❗️

iOS 11.2 以上版本的 Universal Link 行为不一致

从 iOS 11.2+开始,移动应用行业报告 Apple 的 AASA 文件有时可能在应用安装过程中无法下载到用户的设备上。因此,Universal Link 可能无法启用,并且您的应用将无法持续打开。您可以通过在 Branch Link 上设置强制 uri 重定向模式来缓解此问题,以回退到使用 URI scheme 打开应用。请在 Apple Bug 报告中查看问题的详细信息。

配置 Branch

图片图片

配置 Bundle ID

图片图片

配置 Associated Domain

图片图片

配置权利

图片图片

配置 Info.plist

  • 添加 Branch 操作后台 (Dashboard)的值

    • branch_universal_link_domains 添加您的 live key domain
    • branch_key 下添加您当前的 Branch key
    • 将您的 URI scheme 添加为URL Types-> Item 0-> URL Schemes

确认应用前缀(App Prefix)

安装 Branch

通过 Swift Package Manager

Swift Package Manager

  1. In Xcode, add https://github.com/BranchMetrics/ios-branch-sdk-spm as a Swift Package dependency.

🚧

Please use ios-branch-sdk-spm repo with Swift Package Manager

Please use the special https://github.com/BranchMetrics/ios-branch-sdk-spm repository with Swift Package Manager. This makes for much faster installation and a better experience using the Branch SDK with SPM due to the large size of the main iOS repo. The released contents are identical.

Note: The repository is no longer named ios-spm. If you installed using ios-spm, it will continue to work until you have a chance to change to https://github.com/BranchMetrics/ios-branch-sdk-spm. If you are installing for the first time, please use ios-branch-sdk-spm.

Xcode 12

In the Project Navigator, select an app target. Under Frameworks, Libraries and Embedded Content, click +. From Add Other... select Add Package Dependency.... Type or paste in https://github.com/BranchMetrics/ios-branch-sdk-spm. Click Next.

Click Next again to add the Branch framework.

Click Finish to complete the installation.

The Branch framework will now appear in your Swift Package Dependencies.

Xcode 13 beta

In the Project Navigator, select an app target. Under Frameworks, Libraries and Embedded Content, click +. From Add Other... select Add Package Dependency.... Type or paste https://github.com/BranchMetrics/ios-branch-sdk-spm into the search bar and click return to search. Click Next when you see ios-branch-sdk-spm.

Select the Branch framework and click Add Package.

The Branch framework will now appear in your Swift Package Dependencies.

  1. 将以下依赖项导入到Linked Frameworks
  • CoreServices
  • SystemConfiguration 适用于连接类型
  • CoreTelephony 适用于移动运营商
  • WebKit 适用于 Web 浏览器用户代理
  • CoreSpotlight 适用于 Spotlight
  • AdServices 对于 Apple 归因令牌可选
  • iAd 对于 Apple Search Ads 归因可选
  • AdSupport 对于 IDFA 可选

通过 CocoaPods

CocoaPods

platform :ios, '9.0'

target 'APP_NAME' do
  # if swift
  use_frameworks!

  pod 'Branch'
end
pod install && pod update

📘

默认情况下包括 iAd 支持

随着 v0.28.0的发布,iOS 版 Branch SDK 现在包括通过 CocoaPods 安装时 iAD 的所有必需依赖项。

📘

AdSupport 默认情况下不再包含框架

随着 v0.35.0版本的发布,按照即将进行的 IDFA 更改,iOS 的 Branch SDK 包括AdSupport框架。如果您想利用 IDFA(当可用时),我们建议您将AdSupport导入链接框架中

📘

AdServices Framework

在 SDK v1.39.1 + 上,我们建议您导入 AdServices 框架以利用 Apple 广告归因 API。

通过 Carthage

🚧

Carthage 0.36.xxcframework 支持所需

直到 0.37.0+ 版本才包括对 xcframeworks 的 Carthage 支持。

Carthage

Branch 需要 Carthage --use-xcframeworks选项。

github "BranchMetrics/ios-branch-deep-linking"

将以下依赖项导入到Linked Frameworks

  • CoreServices
  • SystemConfiguration 适用于连接类型
  • CoreTelephony 适用于移动运营商
  • WebKit 适用于 Web 浏览器用户代理
  • CoreSpotlight 适用于 Spotlight
  • AdServices 对于 Apple 归因令牌可选
  • iAd 对于 Apple Search Ads 归因可选
  • AdSupport 对于 IDFA 可选

通过 Manual framework

手动安装具有依赖项的 Branch xcframework

注意:如果您喜欢静态 xcframework ,请下载 Branch SDK v1.38.0 + 提供的预构建的 Branch-static zip 文件

将以下依赖项导入到Linked Frameworks

  • CoreServices
  • SystemConfiguration 适用于连接类型
  • CoreTelephony 适用于移动运营商
  • WebKit 适用于 Web 浏览器用户代理
  • CoreSpotlight 适用于 Spotlight
  • AdServices 对于 Apple 归因令牌可选
  • iAd 对于 Apple Search Ads 归因可选
  • AdSupport 对于 IDFA 可选

初始化 Branch

🚧

Branch SDK and Firebase SDK

If you are using both the Branch SDK and the Firebase SDK for deep linking, you must configure Branch initialization differently. After completing the steps below, visit how to Handle Branch Links when using Branch & Firebase SDK

不使用 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

使用 Scenes 的应用

📘

使用 iOS 场景

如果您的应用使用 iOS Scenes,请使用下面的代码示例。

  • 在您的应用的 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
  • 在您的应用的 SceneDelegate 文件中:
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

Apps using SwiftUI

  • Create an AppDelegate.swift file in your project:
import UIKit
import Branch

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        
        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
    }
    
}
  • In your App.swift file:
import SwiftUI
import Branch

@main
struct YourAppNameApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL(perform: { url in
                    Branch.getInstance().handleDeepLink(url)
                })
        }
    }
}

追踪用户

  • 设置事件,深度链接和推荐的用户身份(电子邮件,ID,UUID 等)

❗️

Invoke setIdentity after initSession

This method should only be invoked after initSession completes, either within the callback or after a delay. If it is invoked before, then we will silently initialize the SDK before the callback has been set in order to carry out this method's required task. As a result, you may experience issues where the initSession callback does not fire.

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

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

// logout
[[Branch getInstance] logout];

附录

为 Universal Email 添加 CTD

如果使用 Branch 的 Universal Email 集成,您必须将 ESP 的 CTD 添加到 Associated Domain 权限中,以便在 iOS 中打开链接。这能够使 Apple 将点击追踪域识别为 Universal Link,并在无需打开浏览器的情况下立即打开应用。

  1. 在 Xcode 中,转到项目文件的Capabilities 选项卡。

  2. 向下滚动并启用Associated Domains (如果尚未启用)。

    图片图片

  3. Branch 收到的邮件中复制点击追踪域,或从 ESP 设置中获取。

  4. Domains 部分中,点击+ 图标,然后添加您的点击追踪域。例如,如果您的点击追踪域为email.example.com ,则为applinks:email.example.com添加一个条目。

    图片图片

25 天前更新


iOS 基本集成


建议的编辑仅限于 API 参考页

您只能建议对 Markdown 正文内容进行修改,而不能建议对 API 说明进行修改。