TwinPushSDK 4.0.0

TwinPushSDK 4.0.0

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布最后发布2020年3月

Guillermo Gutiérrez维护。



  • TwinCoders

TwinPush SDK 库

Badge w/ Version Badge w/ Platform License MIT

TwinPush平台提供原生iOS SDK。

安装

要开始使用TwinPush,您需要在iOS应用程序中集成TwinPush SDK。您可以使用TwinPush SDK源代码下载一个工作示例。

使用CocoaPods

CocoaPods(您应该使用CocoaPods)是安装TwinPush SDK最简单、最可维护的方式。如果您正在使用CocoaPods(您应该使用它),请按照以下步骤操作:

  1. TwinPush SDK pod的引用添加到您的Podfile中。

    pod 'TwinPushSDK'
    
  2. 在命令行中执行安装pods的命令

    pod install
    

复制源代码

如果没有使用 CocoaPods,您可以将源代码复制到项目中以链接 SDK

  1. 下载 TwinPush SDK 并解压文件

  2. TwinPushSDK 文件夹和 TwinPushSDK.xcodeproj 文件复制到项目目录下的 Frameworks/TwinPushSDK

  3. TwinPushSDK.xcodeproj 拖放到 XCode 项目中的 Frameworks 目录,以便添加对 TwinPush SDK 项目的引用

  4. 转到项目目标的“构建阶段”部分

    1. TwinPushSDK 添加到 目标依赖 子部分

    2. libTwinPushSDK.a 添加到 链接库 子部分

  5. 转到项目根的“构建设置”部分

    1. 将 TwinPushSDK 文件夹添加到 '用户头文件搜索路径',并将递归设置为 YES
    ${PROJECT_DIR}/ProjectName/Frameworks/TwinPushSDK
    

    确保显示的路径与 TwinPush SDK 框架目录的绝对路径匹配

    1. 将标志 -ObjC 添加到 '其他链接器标志'
  6. 在项目目标的“常规”部分,在“链接框架和库”子部分中,添加以下框架

    MobileCoreServices.framework
    CFNetwork.framework
    SystemConfiguration.framework
    CoreLocation.framework
    libz.dylib
    

Swift 兼容性

Swift 是苹果公司为 Cocoa 和 Cocoa Touch 创建的一种创新的新的编程语言。TwinPush SDK 与 Swift 项目 100% 兼容。

要在 Swift 项目中使用 TwinPush SDK,您可以使用上述任何方法安装 SDK。当使用 CocoaPods 时,您将有一个 TwinPushSDK 模块可供导入,如果您已复制源代码,您必须在桥接头文件中导入 TwinPushManager.h,以便从 Swift 代码中访问它。

有关更多信息,请参阅 Swift 和 Objective-C 在同一项目中

基本 TwinPush SDK 集成

基本集成包括接收简单推送通知所需的所有内容。

使您的应用程序代理(通常命名为 AppDelegate)实现 TwinPushManagerDelegate 并添加这些方法

// Objective-C
#import "TwinPushManager.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate, TwinPushManagerDelegate> 

- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     [TwinPushManager manager].serverSubdomain = SUBDOMAIN;
    [[TwinPushManager manager] setupTwinPushManagerWithAppId:TWINPUSH_APP_ID apiKey:TWINPUSH_API_KEY delegate:self];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog("Registered for remote notifications with token: %@", deviceToken)
    [[TwinPushManager manager] application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary*)userInfo {
    // Stuff to do in this method
    [[TwinPushManager manager] application:application didReceiveRemoteNotification:userInfo];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Application did fail registering for remote notifications: %@", error);
}

@end
// Swift
import TwinPushSDK

class AppDelegate: UIResponder, UIApplicationDelegate, TwinPushManagerDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        TwinPushManager.singleton().serverSubdomain = SUBDOMAIN;
        TwinPushManager.singleton().setupTwinPushManager(withAppId: TWINPUSH_APP_ID, apiKey: TWINPUSH_API_KEY, delegate: self)
        return true
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        NSLog("Registered for remote notifications with token: %@", deviceToken.base64EncodedString())
        TwinPushManager.singleton().application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        TwinPushManager.singleton().application(application, didReceiveRemoteNotification: userInfo)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        NSLog("Failed to register for remote notifications with error: %@", (error as NSError).localizedDescription)
    }
}

SUBDOMAINTWINPUSH_APP_IDTWINPUSH_API_KEY 替换为您在 app.twinpush.com 中的应用程序配置值。必须在调用除设置子域或更改服务器 URL 之外的任何其他 TwinPushSDK 方法之前调用 setupTwinPushManagerWithAppId 方法。

此时,您应该能够正确注册到 TwinPush,并且如果应用程序和服务器证书都已正确配置,则应能够接收推送通知。如果不正确,请检查故障排除部分。

高级 SDK 集成

如果您成功遵循了前面的步骤,您应该能够通过TwinPush接收推送通知。为了充分利用TwinPush,您可以通过改善应用中的SDK集成来获取用户位置、自定义丰富通知查看器或通知收件箱。

请记住,您可以通过查看SDK源代码中包含的Demo项目的源代码来查看一个可工作的示例。

更新徽章计数

服务器徽章计数用于自动增量徽章计数。当应用启动或收到应用已打开的远程通知时,TwinPush SDK会自动将应用程序和服务器徽章计数重置为零。您可以通过将TwinPushManager的autoResetBadgeNumber属性设置为NO来禁用此行为。

此外,您可以通过在任何位置调用TwinPushManager的setApplicationBadgeCount:方法来更新应用程序的本地和服务器徽章计数。

// Objective-C
// Disable auto reset badge number on application startup
[TwinPushManager manager].autoResetBadgeNumber = NO;
// Update application badge count
[[TwinPushManager manager] setApplicationBadgeCount:0];
// Swift
// Disable auto reset badge number on application startup
TwinPushManager.singleton().autoResetBadgeNumber = false
// Update application badge count
TwinPushManager.singleton().setApplicationBadgeCount(0)

获取服务器徽章计数

当发送新的通知时,服务器将更新徽章计数。您可以通过调用TwinPushManager的getApplicationBadge方法获取远程服务器徽章计数。

// Objective-C
[[TwinPushManager manager] getApplicationBadgeOnComplete:^(NSInteger badge) {
    NSLog(@"Obtained remote badge count: %d", (int)badge);
} onError:^(NSError *error) {
    NSLog(@"Received error: %@", error);
}];
// Swift
TwinPushManager.singleton().getApplicationBadge(
    onComplete: { badge in print("Obtained remote badge count: \(badge)") },
    onError: { error in print("Received error: \(error!)") }
)

为设备分配别名

在TwinPush中,别名是一种识别用户而不是设备的方法。它可以很好地向使用不同设备的用户发送推送通知。别名通常是用户标识符、电子邮件或任何其他用于唯一识别用户的值。相同的别名可以分配给不同的设备,发送给该别名的推送通知将到达所有这些设备。

要为设备分配别名,只需分配TwinPushManager的alias属性,它将自动使用该别名注册到TwinPush。

// Objective-C
- (void)loginSuccessfulWithUsername:(NSString*)username {
    [TwinPushManager manager].alias = username;
}
// Swift
func loginSuccessful(username: String) {
    TwinPushManager.singleton().alias = username
}

设备将继续与该别名关联,直到将别名属性设置为不同值。要删除设备的别名,只需将别名设置为nil。

发送用户信息

TwinPush SDK 会自动发送用户设备信息,例如操作系统版本、设备模型或当前区域设置。您可以发送您后续可用于细分推送目标或生成统计信息的其他应用程序用户信息。《TwinPushManager》提供了发送文本、枚举、布尔、整数和浮点值的方法。

您要分配给每个属性的名称将在 TwinPush 网络门户中可见。

// Objective-C
TwinPushManager* twinPush = [TwinPushManager manager];
[twinPush setProperty: @"name" withStringValue: @"Bruce Banner"];
[twinPush setProperty: @"gender" withEnumValue: @"Male"];
[twinPush setProperty: @"allow notifications" withBooleanValue: @(YES)];
[twinPush setProperty: @"age" withIntegerValue: @(45)];
[twinPush setProperty: @"rating" withIntegerValue: @(7.45)];
[twinPush setProperty: @"interests" withEnumListValue: @[ @"Movies", @"Videogames", @"Comics" ]];
// Swift
let twinPush: TwinPushManager = TwinPushManager.singleton()
twinPush.setProperty("name", withStringValue: "Bruce Banner")
twinPush.setProperty("gender", withEnumValue: "Male")
twinPush.setProperty("allow notifications", withBooleanValue: true)
twinPush.setProperty("age", withIntegerValue: 45)
twinPush.setProperty("rating", withFloatValue: 7.45)
twinPush.setProperty("interests", ["Movies", "Videogames", "Comics"])

将属性值设置为 nil 以删除当前设备上的该属性。

条件注册

有时您不希望在应用程序启动后立即将设备注册到 TwinPush。常见场景包括等待成功登录以设置别名或跳过没有推送令牌的注册。《TwinPushManagerDelegate》提供了通过 shouldRegisterDeviceWithAlias 方法控制设备何时应进行注册的方式。要跳过设备的注册,只需返回 NO(或在 Swift 中的 false)即可,设备就不会被注册。

未在平台中注册的设备不会发送使用统计信息,并且无法通过任何方式接收推送通知。

此示例演示了如何避免注册没有别名的设备

// Objective-C
- (BOOL)shouldRegisterDeviceWithAlias:(NSString *)alias token:(NSString *)token {
    return alias.length > 0;
}
// Swift
func shouldRegisterDevice(withAlias alias: String!, token: String!) -> Bool {
    return alias != nil && alias.utf16Count > 0
}

以下事件将触发 TwinPush 中的设备注册:

  • 属性 alias 从上一次注册处发生更改。

  • 属性 pushToken 从上一次注册处发生更改。这通常是调用 TwinPushManager 的便利方法 application:didRegisterForRemoteNotificationsWithDeviceToken: 的结果。

  • 首次调用 TwinPushManagerapplication:didFinishLaunchingWithOptions: 方法。

  • 操作系统版本、应用程序版本或 SDK 版本从上一次注册处发生变化。

  • 明确调用 registerDevice 方法。

使用 shouldRegisterDeviceWithAlias 可以拦截上述所有事件。

注册回调

为了更细粒度地控制 TwinPush 设备注册状态,《TwinPushManagerDelegate》提供了一些方法,以通知注册过程中的事件。这很重要,因为许多 TwinPushManager 在设备尚未注册的情况下将无法将信息发送到服务器。

这些方法包括

  • shouldRegisterDeviceWithAlias:token: 允许条件注册设备。已在前面章节中讨论。

  • didFinishRegisteringDevice 通知设备成功注册或者别名或推送令牌成功更新。

  • didFailRegisteringDevice 通知在尝试注册设备时出现的错误,并提供详细信息。

  • didSkipRegisteringDevice 通知已跳过注册。跳过注册有两个原因: 实现 shouldRegisterDeviceWithAlias 返回了 NO 或者自上次成功注册后没有检测到任何变化。

通知附件

iOS 10 带来了在向用户显示之前修改通知内容的能力。[在此处](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ModifyingNotifications.html)。我们将用它来将图片、音频或视频文件附加到通知中,并且它将显示而不需要打开应用程序。

首先,您必须创建一个新的 通知服务扩展。在 XCode 中,转到 文件 -> 新建 -> 目标,然后选择 通知服务扩展

为此扩展输入一个名称,并确保将其嵌入到您的应用程序中。

它将创建一个新的目标,其中包含一个名为 NotificationService 的单个类。打开它,并将其替换为演示应用程序中提供的 [示例代码](https://github.com/TwinPush/ios-sdk/blob/user-notification-framework/TwinPushSDKDemo/RichNotificationService/NotificationService.m) 的内容。此参考代码将在向用户显示通知之前下载附件(在有效载荷的 attachment 字段中定义)。

为了测试此功能,请确保在扩展的通知有效载荷中将 mutable-content 设置为 1,以便调用扩展。检查 UNNotificationAttachment 参考,以获取支持的文件类型和最大文件大小。

允许不安全的附件 URL

通知服务扩展是一个独立的二进制文件,有它自己的 Info.plist 文件。要从非 https URL(例如:http://)下载内容,必须将具有设置为 YES 的 Allow Arbitrary Loads 标志的 App Transport Security Settings 添加到 扩展的 Info.plist 文件。

交互式通知操作

自定义动作允许用户在选择通知要采取的动作之前无需打开应用程序。为了可以通过平台发送它们,需要在应用程序源代码中进行小型集成。

##### 注册动作类别

为了在应用程序中显示可操作的提醒,您必须注册与类别相关联的动作。

以下代码是从 SDK 示例中摘取的。

// Objective-C
if (![UNNotificationAction class]) {
    // Requires iOS 10 or higher
    return;
}

UNNotificationAction* openAction = [UNNotificationAction
                                    actionWithIdentifier:@"OPEN"
                                    title:@"Open"
                                    options:UNNotificationActionOptionForeground];
UNNotificationAction* openInSafariAction = [UNNotificationAction
                                            actionWithIdentifier:@"SAFARI"
                                            title:@"Open in Safari"
                                            options:UNNotificationActionOptionForeground];

UNNotificationCategory* richNotificationCategory = [UNNotificationCategory
                                           categoryWithIdentifier:@"RICH"
                                           actions:@[openAction, openInSafariAction]
                                           intentIdentifiers:@[]
                                           options:UNNotificationCategoryOptionNone];

// Register the notification categories.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center setNotificationCategories:[NSSet setWithObjects: richNotificationCategory, nil]];
// Swift
guard #available(iOS 10, *) else { return }

let openAction = UNNotificationAction(identifier: "OPEN", title: "Open", options: .foreground)
let openInSafariAction = UNNotificationAction(identifier: "SAFARI", title: "Open in Safari", options: [])

let richNotificationCategory = UNNotificationCategory(
    identifier: "RICH",
    actions: [openAction, openInSafariAction],
    intentIdentifiers: [],
    options: [])

// Register the notification categories.
UNUserNotificationCenter.current().setNotificationCategories(Set([richNotificationCategory]))

当使用类别设置为RICH时发送通知,已注册的操作将显示如下。

有关更多信息,请参阅配置类别和可操作通知

处理通知操作响应

一旦设置好类别和操作,您可以通过实现TwinPushManagerDelegate中的方法didReceiveNotificationResponse:并在其中检查通知操作标识符来处理应用程序中的操作响应。

以下代码是从SDK示例中提取的,当选择在Safari中打开按钮时,将在Safari中打开通知URL。

// Objective-C
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response {
    TPNotification* notification = [TPNotification notificationFromUserNotification:response.notification];
    NSURL* richURL = [NSURL URLWithString:notification.contentUrl];
    if ([response.actionIdentifier isEqualToString:@"SAFARI"] && richURL != nil) {
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
            [[UIApplication sharedApplication] openURL:richURL];
        });
    }
    else {
        [self showNotification:notification];
    }
}
// Swift
@available(iOS 10.0, *)
func didReceive(_ response: UNNotificationResponse!) {
    let notification = TPNotification(fromUserNotification: response.notification)
    if response.actionIdentifier == "SAFARI", let urlString = notification?.contentUrl, let richUrl = URL(string: urlString) {
        DispatchQueue.global(qos: .background).async {
            UIApplication.shared.openURL(richUrl)
        }
    }
    else {
        show(notification)
    }
}

注意我们如何检查response.actionIdentifier以确定确切选择了哪个操作。在本例中,如果用户在丰富通知中选择在Safari中打开SAFARI标识符),它将以指定的URL打开Safari。

自定义丰富通知查看器

TwinPush允许向设备发送丰富通知,它包含一个在web视图中显示的URL。默认情况下,TwinPush SDK将显示包含web视图和导航栏的全屏模态视图。您可以使用UIAppearance代理自定义导航栏。如果想进一步自定义,可以创建自己的丰富通知查看器。

最常见的情况是创建TPNotificationDetailViewController的界面,并分配已创建的IBOutlet属性和IBAction方法。TPNotificationDetailViewController已提供一些常见功能,如从TwinPush加载数据或处理UIWebView错误。

如果您需要更复杂的功能,可以继承TPNotificationDetailViewController以重用代码库,或从头开始创建新的丰富内容查看器。无论哪种方式,结果都将是一个UIViewController,它接受通知对象(TPNotification)并在web视图中显示其丰富内容URL。

一旦有了这个控制器,就必须重写默认行为以防止TwinPush显示默认查看器。为此,只需在应用程序代理中实现TwinPushManagerDelegate中声明的showNotification方法,并显示视图控制器。例如

// Objective-C
#pragma mark - TwinPushManagerDelegate
- (void)showNotification:(TPNotification*)notification {
    // Only show content viewer for rich notifications
    if ([notification isRich]) {
        TPNotificationDetailViewController* customViewer = [[TPNotificationDetailViewController alloc] initWithNibName:@"CustomNotificationViewer" bundle:nil];
        customViewer.notification = notification;
        [self.window.rootViewController presentViewController:customViewer animated:YES completion:nil];
    }
}
// Swift
// MARK: TwinPushManagerDelegate
func show(_ notification: TPNotification!) {
    // Only show content viewer for rich notifications
    if let notification = notification, notification.isRich {
        let customViewer = TPNotificationDetailViewController(nibName: "CustomNotificationViewer", bundle: nil)
        customViewer.notification = notification
        self.window?.rootViewController?.present(customViewer, animated: true, completion: nil)
    }
}

用户通知收件箱

TwinPush 还提供通知收件箱视图控制器,让用户浏览收到的丰富通知。这个视图控制器可以被集成到您的应用程序的任何位置,作为一个普通的 UIViewController。您还可以定义一个自定义外观,以匹配您应用程序的 外观和感觉

禁用推送通知的用户即使在没有收到推送警报的情况下也能浏览通知。这允许用户即使在拒绝接收推送通知的情况下也不错过任何重要信息。

要将收件箱包含到您的应用程序中,实例化类(或您的自定义子类)为 TPAliasInboxViewController 并在需要的时候呈现。常见的场景包括在 UINavigationController 中显示收件箱,或在 UITabBarController 的一个标签中或模式化呈现。本示例展示了如何以模式化呈现。

// Objective-C
TPAliasInboxViewController* inboxVC = [[TPAliasInboxViewController alloc] initWithNibName:@"CustomInboxVC" bundle:nil];
[self.window.rootViewController presentViewController:inboxVC animated:YES completion:nil];
// Swift
let inboxVC = TPAliasInboxViewController(nibName: "CustomInboxVC", bundle: nil)
self.window?.rootViewController?.presentViewController(inboxVC, animated: true, completion: nil)

删除收件箱通知

可以通过调用 TPAliasInboxViewControllerdeleteNotification: 方法来删除收件箱通知。本示例展示了如何显示通知表格行滑动删除选项并调用相应的删除方法。在你的 TPAliasInboxViewController 子类中实现以下方法

// Objective-C
- (void)viewDidLoad {
    [super viewDidLoad];
    self.inboxTableView.allowsMultipleSelectionDuringEditing = NO;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        TPNotification* notification = self.notifications[indexPath.row];
        [self deleteNotification:notification];
    }
}
// Swift
override func viewDidLoad() {
    super.viewDidLoad()
    self.inboxTableView.allowsMultipleSelectionDuringEditing = false
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if (editingStyle == .delete) {
        let notification = self.notifications[indexPath.row] as! TPNotification
        self.deleteNotification(notification)
    }
}

基于设备的收件箱通知

用户收件箱要求在呈现收件箱之前分配别名。没有别名的用户在尝试显示基于别名的收件箱时会收到错误。如果你的应用程序没有使用别名,可以使用 TPNotificationInboxViewController 代替 TPAliasInboxViewController 来创建基于设备的收件箱。

发送用户位置

您可以将用户的当前位置发送给 TwinPush,生成统计数据并根据位置对推送通知目标进行分段。

显式位置

如果您已经通过其他方式获取了位置,可以通过调用 setLocation 方法将其发送给 TwinPush。

// Objective-C
CLLocation* location = [[CLLocation alloc] initWithLatitude:40.383 longitude:-3.717];
[[TwinPushManager manager] setLocation:location];
// Or
[[TwinPushManager manager] setLocationWithLatitude:40.383 longitude:-3.717];
// Swift
let location = CLLocation(latitude: 40.383, longitude: -3.717)
TwinPushManager.singleton().setLocation(location)
// Or
TwinPushManager.singleton().setLocationWithLatitude(40.383, longitude: -3.717)

自动定位

TwinPush还为您提供获取和发送定位的功能。在这种情况下,您只需指定精度,TwinPush SDK将启用GPS信号,获取指定精度的用户位置,将其发送到TwinPush服务器,并禁用GPS以节省电量。

// Objective-C
// Update current location and send to TwinPush
[[TwinPushManager manager] updateLocation:kLocationPrecisionFine];
// Swift
// Update current location and send to TwinPush
TwinPushManager.singleton().updateLocation(TPLocationAccuracyFine)

调用此方法将在使用中使用CLLocationManager类中的requestWhenInUseAuthorization方法请求操作系统使用位置权限。要配置您的应用程序以用于使用中位置使用,您必须在您的应用程序Plist文件中添加键NSLocationWhenInUseUsageDescription,并描述为什么您的应用程序需要用户位置。此描述将在请求权限时显示给用户,因此请确保您具有说服力 ;)

示例来自SDK中包含的演示

<key>NSLocationWhenInUseUsageDescription</key>
<string>TwinPush SDK Demo uses your location for demo purposes :)</string>

即使应用程序已关闭或设备重启,此服务也将持续运行。要停止它

// Objective-C
[[TwinPushManager manager] stopMonitoringLocationChanges];
// Swift
TwinPushManager.singleton().stopMonitoringLocationChanges()

自定义设备UDID

设备UDID(唯一设备标识符)是TwinPush用来独一无二地识别每个设备的字符串。默认情况下,它基于Apple推荐使用identifierForVendor,但可以更改为使用您想要的任何标识符。值得注意的替代方案是,对于启用广告的应用程序使用advertisingIdentifier,或者对于AdHoc分发使用OpenUDID

要更改设备标识符,请在调用setupTwinPushManagerWithAppId:之前设置TwinPushManager中公开的属性deviceUDID

// Objective-C
[TwinPushManager manager].deviceUDID = @"myNewID";
// Swift
TwinPushManager.singleton().deviceUDID = "myNewUDID"

务必为每个设备使用唯一的标识符,否则某些设备可能会被覆盖,并且将永远不会接收到推送通知。

自定义域

对于企业解决方案,TwinPush提供在专用服务器上部署平台的可能性。为了处理应用程序向这个新服务器发出的请求,需要指定其自定义URL或域。

TwinPushManager公开了属性serverURL用于更改服务器URL和一个方便的属性serverSubdomain,用于更改仅TwinPush子域。设置serverURLserverSubdomain将覆盖之前设置的任何值。

// Objective-C
[TwinPushManager manager].serverURL = @"https://my-subdomain.twinpush.com/api/v2";
[TwinPushManager manager].serverSubdomain = @"my-subdomain";
// Swift
TwinPushManager.singleton().serverURL = "https://my-subdomain.twinpush.com/api/v2"
TwinPushManager.singleton().serverSubdomain = "my-subdomain"

修改服务器URL必须是调用TwinPushManager的第一次调用。通常,在调用setupTwinPushManagerWithAppId之前是正确的位置。

自定义数据存储

TwinPushManager 默认会将一些数据存储在NSUserDefaults中,以避免向远程服务发送过多的重复请求。可以通过在TwinPushManagerDelegate中实现storeValue:forKeyfetchValue方法来覆盖此存储。

此示例实现使用SimpleKeychain库将数据加密存储在iOS密钥链中

// Objective-C
- (void)storeValue:(NSString *)value forKey:(NSString *)key {
    if (value != nil) {
        [[A0SimpleKeychain keychain] setString:value forKey:key];
    }
    else {
        [[A0SimpleKeychain keychain] deleteEntryForKey:key];
    }
}

- (NSString *)fetchValueForKey:(NSString *)key {
    return [[A0SimpleKeychain keychain] stringForKey:key];
}
// Swift
func storeValue(_ value: String!, forKey key: String!) {
    if (value != nil) {
        A0SimpleKeychain().setString(value, forKey: key)
    }
    else {
        A0SimpleKeychain().deleteEntry(forKey: key)
    }
}
    
func fetchValue(forKey key: String!) -> String! {
    return A0SimpleKeychain().string(forKey: key)
}

请注意,value可能为nil

处理不同环境

为不同环境在TwinPush中注册不同的应用程序是一种常见的实践。为了在编译时区分环境,您可以使用预处理器指令优雅地处理API密钥。

// Objective-C
#ifdef DEBUG
#define TWINPUSH_APP_ID @"<DEVEL_APP_ID>"
#define TWINPUSH_API_KEY @"<DEVEL_API_KEY>"
#else
#define TWINPUSH_APP_ID @"<PROD_APP_ID>"
#define TWINPUSH_API_KEY @"<PROD_API_KEY>"
#endif

[[TwinPushManager manager] setupTwinPushManagerWithAppId:TWINPUSH_APP_ID apiKey:TWINPUSH_API_KEY delegate:self];
// Swift
#if DEBUG
    let tpApiKey = "<DEVEL_API_KEY>"
    let tpAppId = "<DEVEL_APP_ID>"
#else
    let tpApiKey = "<PROD_API_KEY>"
    let tpAppId = "<PROD_APP_ID>"
#endif

TwinPushManager.singleton().setupTwinPushManager(withAppId: tpAppId, apiKey: tpApiKey, delegate: self)

为了保证正确工作,请确保在项目的构建设置中正确定义了DEBUG

您可以根据需要更改这些名称或添加更多配置。默认情况下,将使用Debug配置进行调试,而使用归档时将使用Release配置。您可以在产品 -> 框架 -> 编辑框架视图中更改构建配置。

外部设备注册

外部注册机制允许您用自定义的注册方法替代到/devices/register的标准调用。这提供了完全控制注册的能力,如果您想在另一个平台上执行操作、收集用户信息或注入额外的信息,这非常有用。

要实现此功能,您只需在setup之前在TwinPushManager实例中提供一个自定义的注册块。

// Objective-C
[TwinPushManager manager].externalRegisterBlock = ^(TPRegisterInformation *info, TPRegisterCompletedBlock onComplete) {
    // Perform the registration manually and create a TPDevice from the TwinPush response
    TPDevice* device; // Obtain this device from the /devices/register result
    
    // Invoke onComplete block when the operation has been successful
    onComplete(device);
};
// Swift
TwinPushManager.singleton().externalRegisterBlock = { info, onComplete in
    // Perform the registration manually and create a TPDevice from the TwinPush response
    let device = TPDevice(); // Obtain this device from the /devices/register result
    
    // Invoke onComplete block when the operation has been successful
    onComplete!(device);
}