#ios #push-notification #swiftui #ios14 #firebase-notifications
#iOS #push-уведомление #свифтуи #ios14 #firebase-уведомления
Вопрос:
Я использую SwiftUI 2.0 и пытаюсь реализовать push-уведомления firebase. В новой структуре приложения SwiftUI нет AppDelegate и SceneDelegate, поэтому я создал класс AppDelegate. Мне удалось получать уведомления, но я не могу перейти к определенному представлению при нажатии уведомления. Вот мой код:
@main
struct swiftUiApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
И расширение AppDelegate:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let orders = Orders()
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: (messageID)")
}
if(userInfo["gcm.notification.type"] != nil){
if(userInfo["gcm.notification.type"] as! String == "order"){
//here I need to navigate to OrderView
}
}
}
Ответ №1:
Я столкнулся с точно такой же проблемой и решил ее таким образом:
Я установил AppDelegate
соответствие моего класса ObservableObject
и добавил опубликованное свойство, которое определяет, нужно ли мне показывать представление, специфичное для уведомлений: @Published var openedFromNotification: Bool = false
В AppDelegate
я установил это свойство true
внутри функций userNotificationCenter( ... willPresent ...)
(уведомление, когда приложение активно) или userNotificationCenter( ... didReceive ...)
(уведомление, когда приложение работает в фоновом режиме).
Поскольку AppDelegate
это an ObservableObject
, его можно установить как environmentObject
для contentView:
@main
struct swiftUiApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView().environmentObject(delegate)
}
}
}
Это дает мне доступ к опубликованному свойству внутри моего contentView().
Внутри contentView я просто отображаю представление, специфичное для уведомлений, или стандартное представление, когда приложение открывается нормально, в зависимости от delegate.openedFromNotification
свойства:
struct ContentView: View {
@EnvironmentObject private var delegate: AppDelegate
var body: some View {
if (delegate.openedFromNotification) {
SpecialView().environmentObject(delegate)
} else {
HomeView()
}
}
}
Я передаю EnvironmentObject delegate
в SpecialView(), чтобы я мог вернуть openedFromNotification
свойству значение false, как только мне нужно снова показать стандартный HomeView() .
Это можно расширить, добавив больше опубликованных свойств, если вы хотите, чтобы другие представления отображались, например, для определенных полезных нагрузок уведомлений.
В моем случае у меня есть два таких опубликованных свойства, и на основе значения JSON в данных push-уведомлений я могу перенаправить пользователя в разные части моего приложения.
Комментарии:
1. Это также можно сделать в расширении watchOS, просто добавьте WKExtensionDelegate вместо AppDelegate и добавьте
UNUserNotificationCenter.current().delegate = self
applicationDidFinishLaunching
внутрь.2. Спасибо. Я реализовал это в github.com/binwiederhier/ntfy-ios/commit /… и это работает как заклинание.
Ответ №2:
Это то, что вы ищете?
@main
struct swiftUiApp: App {
@AppStorage("ViewSelection") var ViewSelection = "SetupView" // Can be another type
var body: some Scene {
WindowGroup {
TabView(selection: $ViewSelection) {
SetupView().tag("SetupView")
ContentView().tag("ContentView")
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
}
}
}
Просто убедитесь, что вы изменили имена представлений на свои собственные
Выбор вида является привязкой, поэтому просто что-то вроде
ViewSelection = "ContentView"
изменит его
Комментарии:
1. мне нужно изменить представление из делегата приложения, потому что мне нужно передать параметры, это не сработает