iOS 基本集成
SDK 统计
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。
1. Configure the Branch Dashboard
- Configure the default link settings for your app
- Make sure
I have an iOS app
is enabled

- Apple App Prefix is your Team ID from your Apple Developer Account

2. Configure Bundle Identifier
- Make sure the Bundle ID matches your Branch Dashboard

3. 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-
要使用 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

4. Configure Entitlements
- Confirm entitlements are within target (This file is configured automatically when completing the steps above in Capabilities tab of Xcode)

5. Configure Info.plist
- Add Branch Dashboard values
- 添加
branch_universal_link_domains
with your live key domain - 添加
branch_key
with your current Branch keys - Add your URI scheme as
URL Types
>Item 0
>URL Schemes
- 添加

- The Info.plist can also be configured by pasting this XML snippet into the source code.
<key>branch_universal_link_domains</key>
<array>
<string>timber.app.link</string>
<string>timber-alternate.app.link</string>
<string>timber.test.app.link</string>
<string>timber-alternate.test.app.link</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>Timber</string>
</array>
<key>CFBundleURLName</key>
<string>io.Branch.Timber</string>
</dict>
</array>
<key>branch_key</key>
<dict>
<key>live</key>
<string>key_live_hd1YSj4JCoSXyxk9R2jsyjrclAslPL21G</string>
<key>test</key>
<string>key_test_pl5EWe1UNaOQyus7V2ipnasydFspH54C</string>
</dict>
6. Install Branch
Please choose one of the following integration methods to install the Branch SDK into your app.
通过 Swift Package Manager
- 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 13
In Xcode, go to File -> Add Packages -> Type or paste https://github.com/BranchMetrics/ios-branch-sdk-spm into the search bar and click return to search.
Select the Branch framework and click Add Package to continue through the installer.

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

- 将以下依赖项导入到Linked Frameworks :

Linked Framework/Libraries | Import Status | 描述 |
---|---|---|
必要项 | Access and manage key operating system services, such as launch and identity services. | |
必要项 | Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active. Used for connection type. | |
必要项 | Access information about a user’s cellular service provider, such as its unique identifier and whether the carrier allows VoIP. Used for mobile carrier. | |
必要项 | Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs. Used for web browser user agent. | |
必要项 | Index your app so users can search the content from Spotlight and Safari. | |
可选的 | Attribute app-download campaigns that originate from the App Store, Apple News, or Stocks on iOS devices. This is used for obtaining Apple Attribution Token. | |
可选的 | Provide apps with access to an advertising identifier. This will give access to IDFA. | |
可选的 | Provide apps with ability to measure ad-driven installs via SKAdNetwork | |
可选的 | Support customization of share sheet. |
通过 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
默认情况下不再包含框架With the release of v0.35.0, the Branch SDK for iOS does not include the
AdSupport
Framework in anticipation of upcoming changes to IDFA. We recommend you importAdSupport
into Linked Frameworks if you want to leverage IDFA when available.
AdServices
FrameworkOn SDK v1.39.1+, we recommend you import
AdServices
Framework to leverage the Apple Ads Attribution API.
通过 Carthage
Carthage 0.36.xxcframework 支持所需
直到 0.37.0+ 版本才包括对 xcframeworks 的 Carthage 支持。
Branch requires the Carthage --use-xcframeworks
option.
github "BranchMetrics/ios-branch-deep-linking"
将以下依赖项导入到Linked Frameworks :
Linked Framework/Libraries | Import Status | 描述 |
---|---|---|
必要项 | Access and manage key operating system services, such as launch and identity services. | |
必要项 | Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active. Used for connection type. | |
必要项 | Access information about a user’s cellular service provider, such as its unique identifier and whether the carrier allows VoIP. Used for mobile carrier. | |
必要项 | Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs. Used for web browser user agent. | |
必要项 | Index your app so users can search the content from Spotlight and Safari. | |
可选的 | Attribute app-download campaigns that originate from the App Store, Apple News, or Stocks on iOS devices. This is used for obtaining Apple Attribution Token. | |
可选的 | Provide apps with access to an advertising identifier. This will give access to IDFA. | |
可选的 | Provide apps with ability to measure ad-driven installs via SKAdNetwork | |
可选的 | Support customization of share sheet. |
通过 Manual framework
Manually install the Branch xcframework with dependencies.
注意
If you prefer a static
xcframework
, please download the pre-built Branch-static zip file available with the Branch SDK v1.38.0+.
将以下依赖项导入到Linked Frameworks :
Linked Framework/Libraries | Import Status | 描述 |
---|---|---|
必要项 | Access and manage key operating system services, such as launch and identity services. | |
必要项 | Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active. Used for connection type. | |
必要项 | Access information about a user’s cellular service provider, such as its unique identifier and whether the carrier allows VoIP. Used for mobile carrier. | |
必要项 | Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs. Used for web browser user agent. | |
必要项 | Index your app so users can search the content from Spotlight and Safari. | |
可选的 | Attribute app-download campaigns that originate from the App Store, Apple News, or Stocks on iOS devices. This is used for obtaining Apple Attribution Token. | |
可选的 | Provide apps with access to an advertising identifier. This will give access to IDFA. | |
可选的 | Provide apps with ability to measure ad-driven installs via SKAdNetwork | |
可选的 | Support customization of share sheet. |

7. Initialize 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 的应用
- Update your app's 'AppDelegate.swift'
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 {
Branch.getInstance().application(app, open: url, options: options)
return true
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> 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 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 场景
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)
} else if !connectionOptions.urlContexts.isEmpty {
BranchScene.shared().scene(scene, openURLContexts: connectionOptions.urlContexts)
}
}
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];
} else if ([[connectionOptions URLContexts] count] != 0) {
[[BranchScene shared] scene:scene openURLContexts: [connectionOptions URLContexts]];
}
}
- (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 theinitSession
callback does not fire.
- Validate with the Branch Dashboard
// login
Branch.getInstance().setIdentity("your_user_id")
// logout
Branch.getInstance().logout() // or .logoutWithCallback() to customize further
// login
[[Branch getInstance] setIdentity:@"your_user_id"];
// logout
[[Branch getInstance] logout];
附录
为 Universal Email 添加 CTD
If you use Branch's Universal Email integration, you must add your ESP’s CTD to your Associated Domains entitlement, in order for links to open in iOS. This allows Apple to recognize the click tracking domain as a Universal Link, opening the app immediately without the browser opening.
- In Xcode, go to the
Capabilities
tab of your project file. - 向下滚动并启用Associated Domains (如果尚未启用)。

- Copy your click tracking domain from the email you received from Branch, or retrieve it from your ESP's settings.
- In the
Domains
section, click the+
icon and add your click tracking domain. For example, if your click tracking domain isemail.example.com
, add an entry forapplinks:email.example.com
。

Updated 5 months ago