测试已测试 | ✗ |
语言语言 | Obj-CObjective C |
许可证 | 自定义 |
发布上次发布 | 2016年8月 |
由Alex Austin,Derrick Staten,Sahil Verma,Ahmed Nawar,Edward Smith,Sahil,sojan pr维护。
依赖 | |
Branch | >= 0 |
HMSegmentedControl | ~> 1.5.2 |
该SDK的目的是为使用Branch SDK的App提供开箱即用的功能“邀请功能”。
仪表板仍有一些配置,但目标是提供最具扩展性、使用最简单的完整邀请功能SDK。要了解使用Branch设置App的基础知识,请查看Branch iOS SDK的readme文件。
在你的App中,将有一个触发器来打开邀请UI。这将显示联系人列表,并允许用户选择他们想要邀请的朋友。
邀请的用户将接收到一条消息(通过短信、电子邮件或你实现的自定义服务)。当他们打开此URL时,将被Branch服务器作为“邀请用户”标记,这将在他们的设备上启动你的App时被记住。当邀请用户进入App时,他们将看到欢迎界面(Branch默认设置或自定义屏幕)。此欢迎屏幕包含邀请用户的图片、姓名和id。被邀请的用户可以选择接受邀请或取消并继续独自操作。
只需前往设置创建一个账户,以存储所有的链接数据。
BranchInvite 可在 CocoaPods 中找到。要安装它,只需将以下行添加到您的 Podfile
pod 'BranchInvite'
测试平台项目
https://s3-us-west-1.amazonaws.com/branchhost/Branch-iOS-Invite-TestBed.zip
SDK
https://s3-us-west-1.amazonaws.com/branchhost/Branch-iOS-Invite-SDK.zip
基础源代码位于项目的 带依赖的源 文件夹中。
在注册您的应用后,您可以在仪表板的 设置 页面上获取您的应用密钥。现在您需要将其添加到 YourProject-Info.plist(Swift 的 Info.plist)中。
在调用 SDK 之前,必须在您的应用中启动 Branch。
在常规的 Branch 应用设置之上,您应该在 init 回调中添加一个检查,以检查是否应该显示欢迎屏幕。默认情况下,BranchWelcomeViewController 将根据 Branch 初始化字典中的键来决定这一点。
修改您的 App Delegate 中的以下两个方法
#import <Branch/Branch.h>
#import "BranchWelcomeViewController.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// anything else you need to do in this method
// ...
Branch *branch = [Branch getInstance];
[branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) { // previously initUserSessionWithCallback:withLaunchOptions:
if (!error) {
// params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
// params will be empty if no data found
// ... insert custom logic here ...
}
if ([BranchWelcomeViewController shouldShowWelcome:params]) {
BranchWelcomeViewController *welcomeController = [BranchWelcomeViewController branchWelcomeViewControllerWithDelegate:self branchOpts:params];
[self.window.rootViewController presentViewController:welcomeController animated:YES completion:NULL];
}
}];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// pass the url to the handle deep link call
// if handleDeepLink returns YES, and you registered a callback in initSessionAndRegisterDeepLinkHandler, the callback will be called with the data associated with the deep link
if (![[Branch getInstance] handleDeepLink:url]) {
// do other deep link routing for the Facebook SDK, Pinterest SDK, etc
}
return YES;
}
class AppDelegate: UIResponder, UIApplicationDelegate, BranchWelcomeControllerDelegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// anything else you need to do in this method
// ...
let branch: Branch = Branch.getInstance()
branch.initSessionWithLaunchOptions(launchOptions, andRegisterDeepLinkHandler: { params, error in
if (error == nil) {
// params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
// params will be empty if no data found
// ... insert custom logic here ...
}
if (BranchWelcomeViewController.shouldShowWelcome(params)) {
let welcomeController: BranchWelcomeViewController = BranchWelcomeViewController(delegate: self, branchOpts: params)
self.window!.rootViewController!.presentViewController(welcomeController, animated: true, completion: nil)
}
})
return true
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
// pass the url to the handle deep link call
// if handleDeepLink returns true, and you registered a callback in initSessionAndRegisterDeepLinkHandler, the callback will be called with the data associated with the deep link
if (!Branch.getInstance().handleDeepLink(url)) {
// do other deep link routing for the Facebook SDK, Pinterest SDK, etc
}
return true
}
每当应用被打开时,都会调用 deep link handler,如果用户点击了引导链接,则返回 deep link 数据。
相同的代码还会触发 Branch 事件记录。如果这是用户第一次打开应用,则注册“安装”事件。每次用户打开应用时,都会触发“打开”事件。此项目使用 CocoaPods 构建,目前依赖于 CocoaPods。要将此项目添加到您的应用中,请在您的 Podfile 中添加以下内容
当您调用 Branch initSession 并注册回调时,如果用户刚刚点击了邀请链接,您可以使用以下 Branch 键来检索单个参数。
BRANCH_INVITE_USER_ID_KEY
BRANCH_INVITE_USER_FULLNAME_KEY
BRANCH_INVITE_USER_SHORT_NAME_KEY
BRANCH_INVITE_USER_IMAGE_URL_KEY
此外,在您的项目中某处需要有显示 BranchInviteViewController 的位置,通常是在菜单或者在用户可以手动触发的位置。以下是显示邀请控制器的代码。
- (IBAction)inviteButtonPressed:(id)sender {
id branchInviteViewController = [BranchInviteViewController branchInviteViewControllerWithDelegate:self];
[self presentViewController:branchInviteViewController animated:YES completion:NULL];
}
显示BranchInviteViewController视图控制器的类必须实现InvitiationControllerDelegate。
首先,要自定义用户需要邀请朋友使用的频道,您可以在数组中指定联系提供者,如下所示。此示例将只显示通过短信邀请的联系人。
- (NSArray *)inviteContactProviders {
return @[
// SMS provider
[BranchInviteTextContactProvider textContactProviderWithInviteMessageFormat:@"Check out my demo app with Branch:\n\n%@!"]
// Email provider
//[BranchInviteEmailContactProvider emailContactProviderWithSubject:@"Check out this demo app!" inviteMessageFormat:@"Check out my demo app with Branch:\n\n%@!"],
// Add your own custom provider
//[[MysteryIncContactProvider alloc] init]
];
}
其次,您必须选择将在个性化欢迎界面中显示的参数。
// The full name of the inviting user, which is displayed in the welcome screen.
// Required
- (NSString *)invitingUserFullname {
return @"Graham Mueller";
}
// An identifier for the user, which can be used by the app to tie back to an actual user record in you system.
// Optional, but recommended
- (NSString *)invitingUserId {
return @"shortstuffsushi";
}
// A short name for the inviting user, typically their first name.
// Optional, but recommended
- (NSString *)invitingUserShortName {
return @"Graham";
}
// A url to load the inviting user's image from, shown on the Welcome screen.
// Optional, but recommended
- (NSString *)invitingUserImageUrl {
return @"https://www.gravatar.com/avatar/28ed70ee3c8275f1d307d1c5b6eddfa5";
}
最后,在这里,您可以自定义调整Branch链接功能的特殊参数。下面的代码片段下方是一个表格,列出了预设键以及它们提供的特定类型的功能。
// The BranchInvite will create a pretty generic Branch short url.
// This hook allows you to provide any additional data you desire.
- (NSDictionary *)inviteUrlCustomData {
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
[params setObject:@"Joe's My App Referral" forKey:@"$og_title"];
[params setObject:@"https://s3-us-west-1.amazonaws.com/myapp/joes_pic.jpg" forKey:@"$og_image_url"];
[params setObject:@"Join Joe in My App - it's awesome" forKey:@"$og_description"];
[params setObject:@"http://myapp.com/desktop_splash" forKey:@"$desktop_url"];
return params;
}
注意 如果您想使用以下可选键动态分享内容,则可以自定义每个URL的Facebook OG标签。请使用此Facebook工具来调试您的OG标签!
键 | 值 |
---|---|
"$og_title" | 您希望在社交媒体中显示的标题 |
"$og_description" | 您希望在社交媒体中显示的描述 |
"$og_image_url" | 您希望在社交媒体中显示的图片的URL |
"$og_video" | 视频的URL |
"$og_url" | 您希望在社交媒体中显示的URL |
"$og_app_id" | 您的OG应用ID。可选且很少使用。 |
此外,您还可以通过以下可选键执行自定义重定向
键 | 值 |
---|---|
"$desktop_url" | 在台式机或笔记本电脑上向用户发送的位置。默认为Branch托管sms服务 |
"$android_url" | 如果用户没有安装应用,则发送到Google Play Store的替代URL。目前,Chrome不支持此覆盖。仅当您想创建移动网页启动页面时才需要 |
"$ios_url" | 如果用户没有安装应用,则发送到App Store的替代URL。仅当您想创建移动网页启动页面时才需要 |
"$ipad_url" | 与上述内容相同,但为iPad Store |
"$fire_url" | 与上述内容相同,但为Amazon Fire Store |
"$blackberry_url" | 与上述内容相同,但为Blackberry Store |
"$windows_phone_url" | 与上述内容相同,但为Windows Store |
"$after_click_url" | 当用户从应用返回浏览器时,将其带到此URL。仅限iOS;Android即将推出 |
您可以通过在字典中插入以下可选键来控制每个链接的直接深度链接
键 | 值 |
---|---|
"$deeplink_path" | 您希望我们追加到您的URI的深度链接路径的值。例如,您可以指定 "$deeplink_path": "radio/station/456",然后我们将使用URI "yourapp://radio/station/456?link_click_id=branch-identifier" 打开应用。这主要用于支持旧的深度链接基础设施。 |
"$always_deeplink" | true或false。(默认不进行深度链接)此键可以指定我们的链接服务强制尝试打开应用,即使我们不确定用户是否已安装应用。如果应用未安装,我们将回退到相应的应用商店或$platform_url键。默认情况下,我们只有在用户从Branch链接(已被Branch Cookie和深度链接)中启动会话时才打开应用。 |
邀请屏幕和欢迎屏幕都可以自定义。
我们设计了邀请屏幕以吸引人且直观,至少在我们看来是这样的。您可能会有不同的感受,但不用担心——我们提供了钩子让您自定义外观。
分段控制
我们使用HMSegmentedControl列出联系提供者。一个钩子允许您自行定制分割控制。但是请注意,在此配置方法中添加的事件或提供的分割将不会被保留。
TableViewCell 定制化如果您希望联系人行有不同的外观,您有两个选择。您可以提供自定义类并将其注册到表格中,或者更广泛地使用nib(带有类)。这两个类中都必须接受BranchInviteContactCell 协议。
联系人提供者可能是应用中最大的自定义点。默认实现将提供一些默认选项——电子邮件和短信——这两个都从地址簿中获取。
有时候这还不够。也许您有一个来自不同第三方系统的联系人列表。在这种情况下,您可以创建自己的提供者,该提供者符合BranchInviteContactProvider 协议。此协议需要一系列项目。
一个简单的实现示例
@interface CustomProvider () <BranchInviteContactProvider>
@property (strong, nonatomic) NSArray *cachedContacts;
@end
@implementation CustomProvider
- (void)loadContactsWithCallback:(callbackWithStatus)callback {
[self loadSomethingThatTakesALongTime:^(NSArray *retrievedItems) {
self.cacheItems = retrievedItems;
callback(YES, nil);
}
failure:^(NSError *error) {
callback(NO, error);
}];
}
- (NSString *)loadFailureMessage {
return @"Failed to load custom contacts";
}
// The title of the segment shown in the BranchInviteViewController
- (NSString *)segmentTitle {
return @"Custom Provider";
}
- (NSString *)channel {
return @"my_custom_channel";
}
- (NSArray *)contacts {
return self.cachedContacts;
}
- (UIViewController *)inviteSendingController:(NSArray *)selectedContacts inviteUrl:(NSString *)inviteUrl completionDelegate:(id <BranchInviteSendingCompletionDelegate>)completionDelegate {
return [CustomerController customControllerWithContacts:selectedContacts inviteUrl:inviteUrl completionDelegate:completionDelegate];
}
@end
对于欢迎屏幕,您可以提供一个要显示的自定义视图,但该视图必须符合指定协议。否则,您可以自定义现有控制器的文字颜色和背景颜色。
一个简单的实现示例
@interface CustomerWelcomeScreen () <BranchWelcomeView>
@property (strong, nonatomic) UIButton *customCancelButton;
@property (strong, nonatomic) UIButton *customContinueButton;
@end
@implementation CustomerWelcomeScreen
- (void)configureWithInviteUserInfo:(NSDictionary *)userInviteInfo {
// Note that this view is created completely programmatically. You could load it from a nib or whatever you like.
UILabel *userIdLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 240, 21)];
userIdLabel.text = [NSString stringWithFormat:@"User ID: %@", userInviteInfo[BRANCH_INVITE_USER_ID_KEY]];
[self.view addSubview:userIdLabel];
UILabel *userFullnameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 41, 240, 21)];
userFullnameLabel.text = [NSString stringWithFormat:@"User Fullname: %@", userInviteInfo[BRANCH_INVITE_USER_FULLNAME_KEY]];
[self.view addSubview:userFullnameLabel];
UILabel *userShortNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 62, 240, 21)];
userShortNameLabel.text = [NSString stringWithFormat:@"User Short Name: %@", userInviteInfo[BRANCH_INVITE_USER_SHORT_NAME_KEY]];
[self.view addSubview:userShortNameLabel];
NSString *userImageUrl = userInviteInfo[BRANCH_INVITE_USER_IMAGE_URL_KEY];
UIImageView *userImageView = [[UILabel alloc] initWithFrame:CGRectMake(20, 83, 64, 64)];
[self.view addSubview:userImageView];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:userImageUrl]];
if (!imageData) {
return;
}
UIImage *invitingUserImage = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
userImageView = invitingUserImage;
});
});
self.customCancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.customCancelButton.frame = CGRectMake(20, 200, 50, 32);
[self.customCancelButton setTitle:@"Cancel" forState:UIControlStateNormal];
self.customContinueButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.customContinueButton.frame = CGRectMake(100, 200, 50, 32);
[self.customContinueButton setTitle:@"Continue" forState:UIControlStateNormal];
}
- (UIButton *)cancelButton {
return self.customCancelButton;
}
- (UIButton *)continueButton {
return self.customContinueButton;
}
@end
有关详细信息,请查看两个类的代理。
如果您使用我们的引用功能,您的用户将希望看到一些信息:
此配置可能有些繁琐,因为您需要进行一些复杂的查询以确定这些项目。好消息是,我们已将此功能添加到此SDK中。添加引用屏幕非常简单,只需几行设置。视图可以轻松地以模态方式显示,甚至可以将其放置到标签栏设置中。
对于默认视图(无样式),这非常简单:
- (void)showMyReferrals {
BranchReferralController *controller = [BranchReferralController branchReferralControllerWithDelegate:self]
[self presentViewController:controller animated:YES completion:NULL];
}
当然,与 SDK 中的所有内容一样,引用屏幕是完全可配置的。如果默认视图不符合您的口味,您可以将其自定义视图提供给构造函数,只要它符合BranchReferralView 协议,该协议包含三个需要实现的方法。
- (void)setCreditHistoryItems:(NSArray *)creditHistoryItems {
// this is *all* of the transactions for the user, useful for showing in a list
}
- (void)setReferrals:(NSArray *)referrals {
// this is the set of transactions that were this user *referring* another user
}
- (void)setControllerDisplayDelegate:(id <BranchReferralViewControllerDisplayDelegate>)displayDelegate {
// this delegate allows you to dismiss this view when the user is done viewing
}
您可以在每个头文件中找到更多具体信息,或者尝试示例应用程序以查看工作示例。
Invite SDK 提供的一个附加功能是一个内容分享的简单钩子。应用开发中较为痛苦的一点是经常试图弄懂如何在 AppDelegate 中进行应用路由。分享功能允许你提供一个密钥,当这个密钥存在于 Branch 打开的字典中时,你可以显示相应的屏幕。与其他 SDK 中的项一样,外观完全可定制。
最简单的使用案例是注册 Branch 默认视图,尽管这相当平淡,可能不会与你的应用外观相匹配。请注意,为了让 AppDelegate 能够处理内容视图的关闭,它应该遵循 BranchSharingControllerDelegate
协议。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for sharing any time the branch options contain the sharing text key
[BranchSharing registerForSharingEventsWithKey:BRANCH_SHARING_SHARE_TEXT];
[[Branch getInstance] initSessionWithLaunchOptions:launchOptions isReferrable:YES andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
if (error) {
NSLog(@"Init failed: %@", error);
return;
}
UIViewController *sharingController = [BranchSharing sharingControllerForBranchOpts:params delegate:self];
if (sharingController) {
self.presentingController = self.window.rootViewController;
[self.presentingController presentViewController:sharingController animated:YES completion:NULL];
}
}];
你也可以提供自己的视图和/或控制器来进一步自定义体验。请注意,只有使用默认视图时才需要使用 BRANCH_SHARING_SHARE_TEXT 密钥进行注册。对于你自己的内容,你可以提供对你有用的任何 Branch 连接键!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Register for sharing any time the branch options contain some arbitrary key
ExampleSharingScreenController *controller = [[ExampleSharingScreenController alloc] initWithNibName:@"ExampleSharingScreen" bundle:[NSBundle mainBundle]];
[BranchSharing registerForSharingEventsWithKey:@"my_key_indicating_sharing" controller:controller];
[[Branch getInstance] initSessionWithLaunchOptions:launchOptions isReferrable:YES andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
if (error) {
NSLog(@"Init failed: %@", error);
return;
}
UIViewController *sharingController = [BranchSharing sharingControllerForBranchOpts:params delegate:self];
if (sharingController) {
self.presentingController = self.window.rootViewController;
[self.presentingController presentViewController:sharingController animated:YES completion:NULL];
}
}];
在这种情况下,你的控制器需要遵循 BranchSharingController
协议,类似于以下这样:
@interface ExampleSharingScreenController ()
@property (weak, nonatomic) IBOutlet UILabel *shareTextLabel;
@property (weak, nonatomic) IBOutlet UILabel *shareImageUrlLabel;
@property (weak, nonatomic) IBOutlet UIImageView *shareImageView;
@end
@implementation ExampleSharingScreenController
- (void)configureWithSharingData:(NSDictionary *)sharingData {
NSString *shareText = sharingData[@"my_sharing_text_key"];
NSString *shareImageUrl = sharingData[@"my_sharing_image_key"];
self.shareTextLabel.text = shareText;
self.shareImageUrlLabel.text = shareImageUrl;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:shareImageUrl]];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
self.shareImageView.image = image;
});
});
}
@end
查看示例项目以获取更多具体细节和示例实现。
示例文件夹包含了一个示例应用程序,它使用 Branch Invite 代码。该应用包含了一个基本的运行示例,说明了这个过程,以及如何对其进行自定义。
请注意,默认情况下已将自定义项注释掉 -- 你需要取消注释它们才能看到视图自定义。
要运行此项目,你需要从示例目录中执行 pod install
。
要测试完整周期,
非常感谢 icons8 授权我们使用他们酷炫的图标!