Уведомление SwiftUI нажмите кнопку перейти к определенному представлению

#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. мне нужно изменить представление из делегата приложения, потому что мне нужно передать параметры, это не сработает