1

I'm new to SwiftUI and after a lot of research I can't figure out how to change my tabview tab when I get a notification.

Currently I use @Published var selectedTab in an Observable object to change my tabview tab.

It works very well, but my problem is that I would like to open the application in a particular tab if I get a notification.

How do I communicate from AppDelegate to my observable object to change the selectedTab value?

Many thanks

Rafael R
  • 11
  • 3

3 Answers3

1

Here is my solution :

  1. Create a class NotificationManager : ObservableObject
class NotificationManager : ObservableObject {
    static let instance = NotificationManager()
    @Published var isChanged: Bool = false
}
  1. Use it in AppDelegate under this function for notification :
...

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {

...

NotificationManager.instance.isChanged.toggle()

}

  1. In the view where your TabView is, add this ObservedObject :
@ObservedObject var notificationManager = NotificationManager.instance
  1. In the view where your TabView is, use it in onAppear and onChange
.onAppear {
            if notificationManager.isChanged {
                selection = 2
            }

}
.onChange(of: notificationManager.isChanged) { newValue in
            selection = 2
}

N.B. solution based on @user3441734 code!

If you have a better solution I'm interested ;-)

Flincorp
  • 751
  • 9
  • 22
0

In your Appdelegate class import SwiftUI .

Then on push notification arrives use this method to show the particular View.

extension AppDelegate {

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        let vc = ContentView.init()
        window?.rootViewController = UIHostingController(rootView:vc)
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {

    }
}
Kishore Kumar
  • 4,265
  • 3
  • 26
  • 47
0

Just define it in your View (or in your model, as default value)!

import SwiftUI

struct HomeView: View {
    let tag: Int
    var body: some View {
        Text("\(tag) Tab selected").font(.largeTitle)
    }
}


struct ContentView: View {
    @State var selection = 2
    var body: some View {

        TabView(selection: $selection) {
            HomeView(tag: selection).tabItem {
                Image(systemName: "house")
                Text("1")
            }.tag(1)

            HomeView(tag: selection).tabItem {
                Image(systemName: "house")
                Text("2")
            }.tag(2)

            HomeView(tag: selection).tabItem {
                Image(systemName: "house")
                Text("3")
            }.tag(3)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

When created, second tab is selected "by default"

enter image description here

user3441734
  • 16,722
  • 2
  • 40
  • 59
  • The problem is that I want the second tab selected only if I open the application from a notification – Rafael R Feb 24 '20 at 13:23
  • and what is the trouble? it should work. Once "selection" changed, SwiftUI will recalculate body of your TabView. (even if your app was in inactive state before) – user3441734 Feb 24 '20 at 13:26
  • @RafaelR once you receive notification, set the value of selection, thats all. – user3441734 Feb 24 '20 at 13:32
  • but how can I communicate with my ObservableObject declared in the SceneDelegate from AppDelegate `func application(_ application: UIApplication, didReceiveRemoteNotification...` ? – Rafael R Feb 24 '20 at 14:36
  • @RafaelR is not SwiftUI specific, in code where you reacting to notification set the value in your model. thats all. if from AppDelegate, just update the model there (so, don't change rootViewController, as suggested in some answer bellow, just update your model. – user3441734 Feb 24 '20 at 14:54