Display a view after receiving APNS with SwiftUI
Asked Answered
H

1

1

I want to show a view, after my App received an APNS-Push Notification. I'm using SwiftUI. I followed this tutorial (https://blckbirds.com/post/how-to-navnigate-between-views-in-swiftui-by-using-an-environmentobject/) to create a motherView and a ViewRouter.

MotherView looks like that:

struct MotherView: View {

//    MARK: - Properties
    @EnvironmentObject var viewRouter: ViewRouter
    @State private var isMenuVisible: Bool = false

    var body: some View {
        VStack {
            if viewRouter.currentPage == Constants.Views.login {
                Login_SwiftUIView()
            } else if viewRouter.currentPage == Constants.Views.main {
                MainView(withMenu: $isMenuVisible)
            } else if viewRouter.currentPage == Constants.Views.menu {
                Menu_SwiftUI(withMenu: $isMenuVisible)
            } else if viewRouter.currentPage == Constants.Views.push {
                PushView()
            }
        }
    }
}

ViewRouter is a ObservableObjectClass

class ViewRouter: ObservableObject {

    let objectWillChange = PassthroughSubject<ViewRouter,Never>()

    var currentPage: Constants.Views = Constants.Views.login {
        didSet {
            objectWillChange.send(self)
        }
    }
}

The AppDelegate calls this function, after receiving a Push-Notification:

func presentView(with pushNotification: [String: AnyObject]) {
    //Here I want to set the viewRouter.currentPage = Constants.View.push
}

What would be your suggestions to solve this problem?

Henke answered 2/3, 2020 at 14:24 Comment(0)
U
2

Here is possible approach.

1) Use native Combine publishing in ViewRouter as

class ViewRouter: ObservableObject {
    @Published var currentPage: Constants.Views = Constants.Views.login
}

2) Create member instance of ViewRouter in AppDelegate

class AppDelegate {
   var viewRouter = ViewRouter()

...

func presentView(with pushNotification: [String: AnyObject]) {
    // set here new value
    self.viewRouter.currentPage = Constants.View.push

}

3) In SceneDelegate use viewRouter from AppDelegate as an environment object for ContentView (or MotherView, if you use it as root view)

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {

            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let contentView = ContentView().environmentObject(appDelegate.viewRoute)

            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)

Thus, you use one ViewRoute object modified in AppDelegate and handled in MotherView.

Unlatch answered 2/3, 2020 at 15:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.