自定义 iOS SDK
深层链接
Anchor link to在您的 Info.plist 文件中,添加一个包含 URL Identifier 和 URL Scheme 的 URL types 数组。
在下面的示例中,URL Scheme 是 com.pushwoosh,URL Identifier 是 promotion。

在您的 App Delegate 文件(通常对于 iOS 12 及更低版本是 AppDelegate.m,对于 iOS 13 及更高版本是 SceneDelegate.m)中,按照下面的示例添加相应的 openURL 委托函数。该示例会检查正确的页面,从 URL 中解析 “id” 值,并打开 PromoPageViewController 作为响应。
AppDelegate.swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { let components = URLComponents(url: url, resolvingAgainstBaseURL: false) let page = components?.host var promotionId: String?
if page == "promotion" { return }
let items = components?.queryItems ?? []
for item in items { if item.name == "id" { promotionId = item.value } }
//show PromoPageViewController}- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSString *page = components.host; NSString *promotionId = nil;
//return if this is not a promotion deep link if(![page isEqualToString:@"promotion"]) return NO;
for(NSURLQueryItem *item in components.queryItems) { if([item.name isEqualToString:@"id"]) promotionId = item.value; }
PromoPageViewController *vc = [[PromoPageViewController alloc] init]; vc.promotionId = promotionId [self presentViewController:vc animated:YES completion:nil];}SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let urlContext = URLContexts.first else { return }
let components = URLComponents(url: urlContext.url, resolvingAgainstBaseURL: false) let page = components?.host var promotionId: String?
guard page == "promotion" else { return }
let items = components?.queryItems ?? []
for item in items { if item.name == "id" { promotionId = item.value } }
//show PromoPageViewController}- (void)scene:(UIWindowScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts { UIOpenURLContext *urlContext = URLContexts.anyObject; if (!urlContext) { return; }
NSURLComponents *components = [NSURLComponents componentsWithURL:urlContext.URL resolvingAgainstBaseURL:NO]; NSString *page = components.host; NSString *promotionId = nil;
if (![page isEqualToString:@"promotion"]) { return; }
for (NSURLQueryItem *item in components.queryItems) { if ([item.name isEqualToString:@"id"]) { promotionId = item.value; } }
//show PromoPageViewController}通用链接
Anchor link to通用链接 (Universal Links) 允许用户在点击您网站的链接时直接打开您的应用。与自定义 URL schemes 不同,通用链接使用标准的 https:// URL,并提供更无缝的用户体验。
工作原理
Anchor link to当推送通知包含 https:// URL(在 “url” 或 “l” 参数中)时,SDK 将:
- 使用该 URL 创建一个
NSUserActivity - 调用您应用的通用链接处理程序(
scene:continueUserActivity:或application:continueUserActivity:restorationHandler:) - 如果您的应用不处理该 URL,它将在 Safari 中打开作为后备方案
-
在 Xcode 中配置关联域 (Associated Domains)
将 Associated Domains 功能添加到您的应用并添加您的域名:
applinks:yourdomain.com -
托管 Apple App Site Association 文件
在您的 Web 服务器上的
https://yourdomain.com/.well-known/apple-app-site-association位置创建一个apple-app-site-association文件:{"applinks": {"apps": [],"details": [{"appID": "TEAM_ID.com.your.bundleid","paths": ["/path/*", "/promotion/*"]}]}}将
TEAM_ID替换为您的 Apple Developer Team ID,并将com.your.bundleid替换为您应用的 bundle identifier。 -
实现通用链接处理程序
SceneDelegate.swift(iOS 13+)func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,let url = userActivity.webpageURL else {return}// Handle the Universal Link URLlet components = URLComponents(url: url, resolvingAgainstBaseURL: false)let path = components?.pathif path?.starts(with: "/promotion") == true {// Navigate to promotion screenlet promotionId = components?.queryItems?.first(where: { $0.name == "id" })?.value// Show promotion with promotionId}}- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {return;}NSURL *url = userActivity.webpageURL;if (!url) {return;}// Handle the Universal Link URLNSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];NSString *path = components.path;if ([path hasPrefix:@"/promotion"]) {// Navigate to promotion screenNSString *promotionId = nil;for (NSURLQueryItem *item in components.queryItems) {if ([item.name isEqualToString:@"id"]) {promotionId = item.value;break;}}// Show promotion with promotionId}}AppDelegate.swift(iOS 12 及更早版本,或作为后备)func application(_ application: UIApplication,continue userActivity: NSUserActivity,restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,let url = userActivity.webpageURL else {return false}// Handle the Universal Link URLlet components = URLComponents(url: url, resolvingAgainstBaseURL: false)let path = components?.pathif path?.starts(with: "/promotion") == true {// Navigate to promotion screenreturn true}return false}- (BOOL)application:(UIApplication *)applicationcontinueUserActivity:(NSUserActivity *)userActivityrestorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {if (![userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {return NO;}NSURL *url = userActivity.webpageURL;if (!url) {return NO;}// Handle the Universal Link URLNSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];NSString *path = components.path;if ([path hasPrefix:@"/promotion"]) {// Navigate to promotion screenreturn YES;}return NO;}
发送带有通用链接的推送
Anchor link to创建推送通知时,在 Action 字段中使用您的网站 URL:
https://yourdomain.com/promotion?id=123SDK 将自动将此 URL 路由到您的通用链接处理程序,允许您将用户导航到应用中的相应屏幕。
应用内购买跟踪
Anchor link to默认情况下,应用内购买跟踪是禁用的。如果您想在配置 Customer Journeys 时跟踪应用内购买,请在 info.plist 文件中将 Pushwoosh_PURCHASE_TRACKING_ENABLED 标志设置为 true。您可以在表格中找到可用标志的列表。
如果您想手动跟踪应用内购买,可以使用下面的代码。
在 paymentQueue:updatedTransactions: 委托方法中调用 PushManager 的 sendSKPaymentTransactions 方法
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { // In-Apps Tracking Pushwoosh code here Pushwoosh.sharedInstance().sendSKPaymentTransactions(transactions) // the rest of the code, consume transactions, etc }- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
[[PushNotificationManager pushManager] sendSKPaymentTransactions:transactions];
//the rest of the code, consume transactions, etc}
地理区域推送通知
Anchor link to地理区域推送通知被封装在一个单独的框架 PushwooshGeozones 中。
-
将 PushwooshGeozones.framework 添加到您的项目中
要使用依赖管理器将 PushwooshGeozones.framework 添加到您的项目中,请将以下行放入您的
podfile或cartfile中:pod 'PushwooshXCFramework/Geozones'github "Pushwoosh/pushwoosh-ios-sdk"如果您想使用 PushwooshGeozones.xcframework,请输入以下 Package URL:
PushwooshGeozones-XCFramework或者,您也可以简单地将该框架拖放到项目 Build Phases 中的 Link Binaries With Libraries。
-
将以下键添加到您的 Info.plist 中:
- NSLocationWhenInUseUsageDescription – (必需) 用于应用仅在前台运行时跟踪地理区域。
- NSLocationAlwaysAndWhenInUseUsageDescription – (必需) 用于应用在前台和后台跟踪地理区域,并显示权限请求对话框弹出窗口。
- NSLocationAlwaysUsageDescription – (可选) 用于应用始终跟踪地理区域;如果您的应用目标是 iOS 10 及更早版本,则应使用此项。
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key><string>for app to track Geozones in both conditions and to show a permission request dialog</string><key>NSLocationWhenInUseUsageDescription</key><string>for app to track Geozones only while running in the foreground</string> -
导入框架
import PushwooshGeozones#import <PushwooshGeozones/PWGeozonesManager.h> -
启动地理区域跟踪
PWGeozonesManager.shared()?.startLocationTracking()[[PWGeozonesManager sharedManager] startLocationTracking];
override func viewDidLoad() { super.viewDidLoad()
// 在需要时启动地理区域跟踪 PWGeozonesManager.shared().startLocationTracking()}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view.
// 在需要时启动地理区域跟踪 [[PWGeozonesManager sharedManager] startLocationTracking];}创建富媒体队列
Anchor link to如果需要同时显示多个富媒体页面(例如,两个或多个应用内消息的触发事件同时发生,或者在另一个触发事件发生时已经显示了一个富媒体页面),您可以设置一个富媒体页面显示队列。要创建队列,请按照以下步骤操作。
-
创建一个实现 PWRichMediaPresentingDelegate 的类:
@interface ChainedRichMediaPresentingDelegate () <PWRichMediaPresentingDelegate>@property (nonatomic) NSMutableArray *queue;@property (nonatomic) BOOL inAppIsPresenting;@end@implementation ChainedRichMediaPresentingDelegate- (instancetype)init {self = [super init];if (self) {_queue = [NSMutableArray new];}return self;}- (BOOL)richMediaManager:(PWRichMediaManager *)richMediaManager shouldPresentRichMedia:(PWRichMedia *)richMedia {[_queue addObject:richMedia];return !_inAppIsPresenting;}- (void)richMediaManager:(PWRichMediaManager *)richMediaManager didPresentRichMedia:(PWRichMedia *)richMedia {_inAppIsPresenting = YES;}- (void)richMediaManager:(PWRichMediaManager *)richMediaManager didCloseRichMedia:(PWRichMedia *)richMedia {_inAppIsPresenting = NO;[_queue removeObject:richMedia];if (_queue.count) {[[PWRichMediaManager sharedManager] presentRichMedia:_queue.firstObject];}}- (void)richMediaManager:(PWRichMediaManager *)richMediaManager presentingDidFailForRichMedia:(PWRichMedia *)richMedia withError:(NSError *)error {[self richMediaManager:richMediaManager didCloseRichMedia:richMedia];}@end -
设置委托:
[PWRichMediaManager sharedManager].delegate = [ChainedRichMediaPresentingDelegate new];
通过 Force Touch 自动播放在富媒体通知中发送的视频
Anchor link to要使作为富媒体通知附件发送的视频在通知展开时无需任何用户交互即可自动播放,请按照以下步骤操作:
-
将 Notification Content Extension 添加到您的项目中:
- 在 Xcode 中,选择 File > New > Target。
- 选择 Notification Content Extension。
- 为其分配一个名称并完成设置。

如果出现“激活 scheme”消息提示,请选择 Cancel。

-
如下调整 Content Extension 中的属性和方法:
import UIKitimport UserNotificationsimport UserNotificationsUIimport AVKitclass NotificationViewController: UIViewController, UNNotificationContentExtension {var playerController: AVPlayerViewController!@IBOutlet weak var playerBackgroundView: UIView!override func viewDidLoad() {super.viewDidLoad()// 在此处进行任何所需的界面初始化。}func didReceive(_ notification: UNNotification) {let attachment = notification.request.content.attachments.firstplayerController = AVPlayerViewController()// 以编程方式设置高度// preferredContentSize.height = 250if let url = attachment?.url {setupVideoPlayer(url: url)} else {print("No valid URL...")}}private func setupVideoPlayer(url: URL) {guard let playerController = self.playerController else { return }let player = AVPlayer(url: url)playerController.player = playerplayerController.view.frame = self.playerBackgroundView.boundsplayerBackgroundView.addSubview(playerController.view)addChild(playerController)playerController.didMove(toParent: self)player.play()} -
将一个 UIView 合并到 MainInterface.storyboard 中:

-
将 playerBackgroundView IBOutlet 与您刚刚添加的 UIView 连接起来:

-
使用以下条目更新 info.plist 文件:
UNNotificationExtensionUserInteractionEnabled = true
为了将视频附加到您的通知中,请在控制面板的 Media Attachment 字段中输入视频的 URL:

通过 API /createMessage 请求发送通知时,请在 “ios_attachment” 参数中包含该 URL,并确保 “mutable-content” 标志设置为 `1`。
自定义推送声音
Anchor link to要在收到推送通知时播放自定义声音,首先请将音频文件放入您项目的根文件夹中。

然后,在推送参数中指定声音文件的名称——填写消息的iOS 特定设置中的 Sound 字段,或将文件名指定为 createMessage API 请求 的 “ios_sound” 参数的值。
用于自定义 iOS 声音的音频文件必须是以下格式之一:.aif、.caf、.wav。请确保在文件名中指定格式;否则,Pushwoosh iOS SDK 将会忽略它。
iOS 临时推送
Anchor link to工作原理
Anchor link to临时推送通知会静默地出现在用户的通知中心,但不会出现在锁屏上。这种类型的推送不需要用户明确允许:一旦用户安装并启动您的应用,您就可以开始发送它们。
然而,用户仍然可以订阅您的显式推送通知:当打开临时推送时,他们有两个选项来选择他们的体验——将推送保留在通知中心,不带提醒和声音,或者允许您显式地发送推送,使其出现在锁屏上。
临时推送旨在让用户就他们是否愿意接收来自您应用的通知做出明智的决定。由于 APN 原生订阅请求只向用户显示一次,之后要订阅,他们必须进入手机的系统设置,一些用户可能因为不了解您的推送能带来什么价值而不会订阅。临时推送给予用户这种理解:他们可以看到您在推送通知中传递的内容,并决定是否需要显式地收到这些内容的通知。
如何实现
Anchor link to-
按照指南集成 Pushwoosh iOS SDK。
-
在调用
registerForPushNotifications()方法之前,将以下字符串添加到您项目的 AppDelegate 中:
if #available(iOS 12.0, *) { Pushwoosh.sharedInstance().additionalAuthorizationOptions = UNAuthorizationOptions.provisional}if (@available(iOS 12.0, *)) { [Pushwoosh sharedInstance].additionalAuthorizationOptions = UNAuthorizationOptionProvisional;}就是这样!一旦用户安装了应用,他们将直接在通知中心收到消息。
与我们分享您的反馈
Anchor link to您的反馈有助于我们创造更好的体验,因此如果您在 SDK 集成过程中遇到任何问题,我们很乐意听取您的意见。如果您遇到任何困难,请随时通过此表单与我们分享您的想法。