Разработка
Глубокие ссылки для локальных уведомлений в SwiftUI
Сегодня я хочу поделиться тем, как я создаю глубокие ссылки для локальных уведомлений в своих приложениях.
Уведомления имеют решающее значение для удержания пользователей в приложении. Почти все мои приложения содержат уведомления, которые не только запускают приложение, но и ведут к различным частям приложения. Сегодня я хочу поделиться тем, как я создаю глубокие ссылки для локальных уведомлений в своих приложениях.
В SwiftUI появился модификатор представления onOpenURL
для работы с универсальными ссылками в наших приложениях. Вот краткий пример, показывающий, как использовать модификатор представления onOpenURL
.
@main struct MyApp: App { @State private var offerShown = false var body: some Scene { WindowGroup { ContentView() .onOpenURL { url in guard let host = url.host(), host == "offer" else { return } offerShown = true } .sheet(isPresented: $offerShown) { OfferView() } } } }
Как видно из примера выше, мы используем модификатор представления onOpenURL
, чтобы разобрать открытый URL и обеспечить навигацию внутри приложения, отображая экран с предложением.
Перед использованием модификатора представления onOpenURL
необходимо зарегистрировать схему URL, которую вы хотите открывать в приложении. Перейдите в настройки проекта, выберите цель и зарегистрируйте схему URL в разделе «Типы URL».
Теперь вы готовы работать со ссылками в своем приложении. Вы можете попробовать проверить, как приложение работает со ссылками, открыв ссылку в Safari, например, myapp://offer.
Я хочу запланировать уведомление, которое покажет пользователю специальное предложение после первого запуска через 30 минут. Я написал расширение для UNUserNotificationCenter
, чтобы сделать это проще.
extension UNUserNotificationCenter { func addOfferNotification() { let content = UNMutableNotificationContent() content.title = String(localized: "offerTitle") content.body = String(localized: "offerBody") content.userInfo = ["url": "myapp://offer"] let request = UNNotificationRequest( identifier: "offer", content: content, trigger: UNTimeIntervalNotificationTrigger( timeInterval: 1800, repeats: false ) ) add(request) } }
Как видно из примера выше, я создал функцию addOfferNotification
, чтобы запланировать уведомление через 30 минут. Я указываю заголовок и тело уведомления и включаю поле URL в словарь userInfo
.
Идея заключается в том, чтобы перехватывать уведомления с полем URL в словаре userInfo
и открывать URL вместо запуска приложения. Тип UNUserNotificationCenter
позволяет нам предоставить делегата для обработки момента, когда пользователь нажимает на уведомление.
Единственное место, где вы должны задать делегата для типа UNUserNotificationCenter
, — это метод willFinishLaunchingWithOptions
в AppDelegate. Итак, нам нужно определить AppDelegate для нашего приложения SwiftUI.
final class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { UNUserNotificationCenter.current().delegate = self return true } } extension AppDelegate: UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { guard let urlString = response.notification.request.content.userInfo["url"] as? String, let url = URL(string: urlString) else { return } await UIApplication.shared.open(url) } }
Как видите, мы определяем тип AppDelegate в соответствии с протоколом UIApplicationDelegate
. Мы также соответствуем протоколу UNUserNotificationCenterDelegate
и реализуем функцию didReceive
. Наше приложение будет вызывать эту функцию всякий раз, когда пользователь коснется уведомления, пока приложение находится в фоновом режиме.
Это лучшее место для проверки того, что наше уведомление содержит URL для запуска и открытия этого адреса с помощью общего экземпляра типа UIApplication
. Мы можем игнорировать другие уведомления, не содержащие поле URL.
@main struct MyApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) private var delegate @AppStorage("launches") private var launches = 0 @Environment(\.scenePhase) private var scenePhase @State private var offerShown = false var body: some Scene { WindowGroup { ContentView() .onOpenURL { url in guard let host = url.host(), host == "offer" else { return } offerShown = true } .sheet(isPresented: $offerShown) { OfferView() } } .onChange(of: scenePhase) { switch scenePhase { case .background where launches == 1: UNUserNotificationCenter.current().addOfferNotification() case .active: launches += 1 default: break } } } }
В приведенном выше примере мы используем обертку свойств UIApplicationDelegateAdaptor
, чтобы определить AppDelegate для приложения SwiftUI. Мы также используем обозреватель, чтобы запланировать уведомление о предложении после первого запуска.