Уведомления имеют решающее значение для удержания пользователей в приложении. Почти все мои приложения содержат уведомления, которые не только запускают приложение, но и ведут к различным частям приложения. Сегодня я хочу поделиться тем, как я создаю глубокие ссылки для локальных уведомлений в своих приложениях.
В 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. Мы также используем обозреватель, чтобы запланировать уведомление о предложении после первого запуска.

