Open Specific View When Opening App from Notification

Open a specific view when opening the App through a Notification

By the way: This code only works if the app still runs in the
background,

Instead of .onAppear in ContentView use subscription to publisher, like below

1) Declare publisher

struct ContentView: View {
let todoPublisher = NotificationCenter.default.publisher(for: NSNotification.Name("ToDoView"))
...

2) Add subscriber (in the place you added .onAppear and instead of it)

.onReceive(todoPublisher) { notification in
self.showToDo = true
}

this will work as long as ContentView exists.

Open app in specific view when user taps on push notification with iOS 13 Swift 5

You can trigger a notification once you receive and the user clicks on the notification.

Along with the notification, you can pass the value which will later used to identify to which view controller you need to navigate.

Create a class which will be responsible for all the push notification navigation handling. You can name it like PushNotificationHandler. Let the PushNotificationHandler handler take care of all the logic to navigate to the view controllers.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 
}
  • Get the value from the deep link using the above delegate method
  • Trigger a notification with the value
  • Handle the notification inside PushNotificationHandler class

Swift - How to open specific view controller when push notification received?

When you app is in closed state you should check for launch option in

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { }

and call your API.

Example:

if let option = launchOptions {
let info = option[UIApplicationLaunchOptionsKey.remoteNotification]
if (info != nil) {
goAnotherVC()
}
}

SwiftUI - Open a specific View when user opens a Push Notification

You need some sort of shared state that you can modify that SwiftUI knows to react to. An ObservableObject is perfect for this:

class AppState: ObservableObject {
static let shared = AppState()
@Published var pageToNavigationTo : String?
}

Then, to listen to it and respond to it, you can do a couple different methods in your main view.

Option 1 -- NavigationLink binding based on the value of the ObservedObject:

struct ContentView : View {
@ObservedObject var appState = AppState.shared //<-- note this
@State var navigate = false

var pushNavigationBinding : Binding<Bool> {
.init { () -> Bool in
appState.pageToNavigationTo != nil
} set: { (newValue) in
if !newValue { appState.pageToNavigationTo = nil }
}
}

var body: some View {
NavigationView {
Text("My content")
.overlay(NavigationLink(destination: Dest(message: appState.pageToNavigationTo ?? ""),
isActive: pushNavigationBinding) {
EmptyView()
})
}
}
}

struct Dest : View {
var message : String
var body: some View {
Text("\(message)")
}
}

Or, you could use onReceive:

struct ContentView : View {
@ObservedObject var appState = AppState.shared
@State var navigate = false

var body: some View {
NavigationView {
VStack {
if navigate {
NavigationLink(destination: Text("Test"), isActive: $navigate ) {
EmptyView()
}
}
Text("My content")
.onReceive(appState.$pageToNavigationTo) { (nav) in
if nav != nil { navigate = true }
}
}
}
}
}

I'll leave the implementation details of your specific NavigationView, NavigationLink, TabView, etc to you, but this should get you started.

Finally, a fully-functional minimal example that mocks a notification and shows how the navigation view:


class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("Dispatch")
AppState.shared.pageToNavigationTo = "test"
}

return true
}
}

class AppState: ObservableObject {
static let shared = AppState()
@Published var pageToNavigationTo : String?
}

@main
struct MultiWindowApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate


var body: some Scene {
WindowGroup {
ContentView()
}
}
}

struct ContentView : View {
@ObservedObject var appState = AppState.shared
@State var navigate = false

var pushNavigationBinding : Binding<Bool> {
.init { () -> Bool in
appState.pageToNavigationTo != nil
} set: { (newValue) in
if !newValue { appState.pageToNavigationTo = nil }
}
}

var body: some View {
NavigationView {
Text("My content")
.overlay(NavigationLink(destination: Dest(message: appState.pageToNavigationTo ?? ""),
isActive: pushNavigationBinding) {
EmptyView()
})
}
}
}

struct Dest : View {
var message : String
var body: some View {
Text("\(message)")
}
}

Open specific ViewController from push notification when application closed

If you want to open vc from the closed state of your app, you can check if app was opened from click on Notification in this method of AppDelegate.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 

It looks like:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

// When the app launch after user tap on notification (originally was not running / not in background)
if launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] != nil {

goToEventDetails(userInfo: launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any])

}
}

Where goToEventDetails is method which instantiates VC and pushed id, and [UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] is content of Notification.



Related Topics



Leave a reply



Submit