Кастомизация iOS SDK
Интеграция
Anchor link to- Глубокие ссылки (Deep linking)
- Универсальные ссылки (Universal Links)
- Отслеживание встроенных покупок
- Push-уведомления на основе геозон
- Создание очереди Rich Media
- Автовоспроизведение видео, отправленного в Rich Notification, с помощью Force Touch
- Пользовательский звук push-уведомления
- iOS Provisional Push
Глубокие ссылки (Deep linking)
Anchor link toВ вашем файле Info.plist добавьте массив URL types с URL Identifier и URL Scheme.
В примере ниже URL Scheme — com.pushwoosh, а URL Identifier — promotion.

В файле делегата вашего приложения (обычно AppDelegate.m для iOS 12 и ниже, или SceneDelegate.m для iOS 13 и выше) добавьте соответствующую функцию-делегат openURL, как показано в примере ниже. Пример проверяет корректность страницы, извлекает значение “id” из URL и в ответ открывает 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}Универсальные ссылки (Universal Links)
Anchor link toУниверсальные ссылки позволяют пользователям открывать ваше приложение напрямую, когда они нажимают на ссылку на ваш сайт. В отличие от пользовательских схем URL, универсальные ссылки используют стандартные URL https:// и обеспечивают более плавный пользовательский опыт.
Как это работает
Anchor link toКогда push-уведомление содержит URL https:// (в параметре “url” или “l”), SDK:
- Создаст
NSUserActivityс URL - Вызовет обработчик универсальных ссылок вашего приложения (
scene:continueUserActivity:илиapplication:continueUserActivity:restorationHandler:) - Если ваше приложение не обработает URL, он будет открыт в Safari в качестве запасного варианта
Настройка
Anchor link to- Настройте Associated Domains в Xcode
Добавьте возможность Associated Domains в ваше приложение и укажите ваш домен:
applinks:yourdomain.com- Разместите файл Apple App Site Association
Создайте файл apple-app-site-association на вашем веб-сервере по адресу https://yourdomain.com/.well-known/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 на идентификатор вашего приложения.
- Реализуйте обработчик универсальных ссылок
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 URL let components = URLComponents(url: url, resolvingAgainstBaseURL: false) let path = components?.path
if path?.starts(with: "/promotion") == true { // Navigate to promotion screen let 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 URL NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSString *path = components.path;
if ([path hasPrefix:@"/promotion"]) { // Navigate to promotion screen NSString *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 URL let components = URLComponents(url: url, resolvingAgainstBaseURL: false) let path = components?.path
if path?.starts(with: "/promotion") == true { // Navigate to promotion screen return true }
return false}- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(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 URL NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSString *path = components.path;
if ([path hasPrefix:@"/promotion"]) { // Navigate to promotion screen return YES; }
return NO;}Отправка push-уведомления с универсальной ссылкой
Anchor link toПри создании push-уведомления используйте URL вашего сайта в поле Action:
https://yourdomain.com/promotion?id=123SDK автоматически направит этот URL в ваш обработчик универсальных ссылок, позволяя вам перевести пользователя на соответствующий экран в вашем приложении.
Отслеживание встроенных покупок
Anchor link toПо умолчанию отслеживание встроенных покупок отключено. Если вы хотите отслеживать встроенные покупки при настройке Customer Journeys, установите флаг Pushwoosh_PURCHASE_TRACKING_ENABLED в значение true в файле info.plist. Список доступных флагов можно найти в таблице.
Если вы хотите отслеживать встроенные покупки вручную, вы можете использовать код ниже.
В методе-делегате paymentQueue:updatedTransactions: вызовите метод sendSKPaymentTransactions из PushManager
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}
Push-уведомления на основе геозон
Anchor link toPush-уведомления на основе геозон инкапсулированы в отдельный фреймворк PushwooshGeozones.
- Добавьте PushwooshGeozones.framework в ваш проект
Чтобы добавить PushwooshGeozones.framework в ваш проект с помощью менеджера зависимостей, добавьте следующие строки в ваш podfile или cartfile:
pod 'PushwooshXCFramework/Geozones'github "Pushwoosh/pushwoosh-ios-sdk"Если вы хотите использовать PushwooshGeozones.xcframework, введите следующий URL пакета:
PushwooshGeozones-XCFramework
В качестве альтернативы вы можете просто перетащить фреймворк в Link Binaries With Libraries в Build Phases вашего проекта.
- Добавьте следующие ключи в ваш 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];Пример
Anchor link tooverride func viewDidLoad() { super.viewDidLoad()
// Start Geozones tracking when needed PWGeozonesManager.shared().startLocationTracking()}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view.
// Start Geozones tracking when needed [[PWGeozonesManager sharedManager] startLocationTracking];}Создание очереди Rich Media
Anchor link toВ случае, если необходимо одновременно отобразить несколько страниц Rich Media (например, триггерные события для двух или более In-App сообщений происходят в один момент, или страница Rich Media уже отображается в момент, когда происходит другое триггерное событие), вы можете настроить очередь для отображения страниц Rich Media. Чтобы создать очередь, выполните шаги, описанные ниже.
- Создайте класс, который реализует 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];}
@end2. Установите делегата:
[PWRichMediaManager sharedManager].delegate = [ChainedRichMediaPresentingDelegate new];Автовоспроизведение видео, отправленного в Rich Notification, с помощью Force Touch
Anchor link toЧтобы видео, отправленное как вложение Rich Notification, автоматически воспроизводилось при разворачивании уведомления без какого-либо взаимодействия с пользователем, выполните следующие шаги:
- Добавьте Notification Content Extension в ваш проект:
- В Xcode выберите File > New > Target.
- Выберите Notification Content Extension.
- Присвойте ему имя и завершите настройку.

Если появится сообщение “Activate scheme”, выберите Cancel.

- Настройте свойства и методы в Content Extension следующим образом:
import UIKitimport UserNotificationsimport UserNotificationsUIimport AVKit
class NotificationViewController: UIViewController, UNNotificationContentExtension { var playerController: AVPlayerViewController! @IBOutlet weak var playerBackgroundView: UIView!
override func viewDidLoad() { super.viewDidLoad() // Do any required interface initialization here. }
func didReceive(_ notification: UNNotification) { let attachment = notification.request.content.attachments.first
playerController = AVPlayerViewController() // Set height programmatically // preferredContentSize.height = 250
if 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 = player playerController.view.frame = self.playerBackgroundView.bounds playerBackgroundView.addSubview(playerController.view) addChild(playerController) playerController.didMove(toParent: self) player.play() }- Включите UIView в MainInterface.storyboard:

- Свяжите IBOutlet playerBackgroundView с только что добавленным UIView:

- Обновите файл info.plist, добавив следующую запись:
UNNotificationExtensionUserInteractionEnabled = true
Чтобы прикрепить видео к вашему уведомлению, введите URL видео в поле Media Attachment в Control Panel:

При отправке уведомления через API-запрос /createMessage включите URL в параметр “ios_attachment” и убедитесь, что флаг “mutable-content” установлен в `1`.
Пользовательский звук push-уведомления
Anchor link toЧтобы воспроизвести пользовательский звук при получении push-уведомления, сначала поместите аудиофайл в корневую папку вашего проекта.

Затем укажите имя звукового файла в параметрах push-уведомления – заполните поле Sound в настройках для iOS вашего сообщения или укажите имя файла в качестве значения для параметра “ios_sound” в API-запросе createMessage.
Аудиофайл для пользовательского звука iOS должен быть в одном из следующих форматов: .aif, .caf, .wav. Обязательно укажите формат в имени файла; в противном случае он будет проигнорирован Pushwoosh iOS SDK.
iOS Provisional Push
Anchor link toКак это работает
Anchor link toProvisional push-уведомления появляются беззвучно в Центре уведомлений пользователя, но не на экране блокировки. Этот тип push-уведомлений не требует явного разрешения от пользователя: вы можете начать отправлять их, как только пользователь установит и запустит ваше приложение.
Однако пользователи все равно могут подписаться на ваши обычные push-уведомления: при открытии Provisional Push у них есть два варианта выбора – оставить push-уведомления в Центре уведомлений без оповещений и звуков или разрешить вам отправлять push-уведомления в обычном режиме, чтобы они появлялись на экране блокировки.
Provisional Pushes разработаны для того, чтобы пользователи могли принимать обоснованные решения о том, хотят ли они получать уведомления от вашего приложения. Поскольку нативный запрос на подписку APN показывается пользователям только один раз, и чтобы подписаться позже, им нужно зайти в системные настройки телефона, некоторые пользователи могут не подписываться, так как не знают, какую ценность они получат от ваших push-уведомлений. Provisional Pushes дают пользователям это понимание: они могут видеть, какой контент вы доставляете в push-уведомлениях, и решать, нужно ли им получать уведомления об этом контенте в обычном режиме.
Как реализовать
Anchor link to1. Интегрируйте Pushwoosh iOS SDK, следуя руководству.
2. Добавьте следующую строку в AppDelegate вашего проекта перед вызовом метода registerForPushNotifications():
if #available(iOS 12.0, *) { Pushwoosh.sharedInstance().additionalAuthorizationOptions = UNAuthorizationOptions.provisional}if (@available(iOS 12.0, *)) { [Pushwoosh sharedInstance].additionalAuthorizationOptions = UNAuthorizationOptionProvisional;}Вот и все! Пользователи приложения будут получать сообщения прямо в свой Центр уведомлений после установки приложения.
Поделитесь с нами своим мнением
Anchor link toВаши отзывы помогают нам создавать лучший опыт, поэтому мы будем рады услышать от вас, если у вас возникнут какие-либо проблемы в процессе интеграции SDK. Если вы столкнетесь с какими-либо трудностями, пожалуйста, не стесняйтесь поделиться своими мыслями с нами через эту форму.