I am making an iOS application. Where I have made that I get notification when near certain places. And that works fine. But I then want it to navigate to a certain view when I press the notification.
I am thinking just like when I get a sms. I press that notification for the sms and it then navigate me to the correct sms conversation.
When application receives a push notification, a method in UIApplicationDelegate is called. The notification needs to be handled differently depending on what state your app is in when it’s received:
If app wasn’t running and the user launches it by tapping the push
notification, the push notification is passed to your app in the
launchOptions of
application(_:didFinishLaunchingWithOptions:)
If app was running and in the foreground, the push notification
will not be shown this function will call immediately
application(_:didReceiveRemoteNotification:)
If app was running or suspended in the background and the user brings
it to the foreground by tapping the push notification, this function
will be called.
application(_:didReceiveRemoteNotification:)
So you can change the root view controller on these functions like this :-
if let notification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [String: AnyObject] {
//Change your root view controller
}
This checks whether the value for UIApplicationLaunchOptionsRemoteNotificationKey exists in launchOptions. If it does, this will be the push notification payload you sent.
I wrote a simple class to navigate to any view controller in the view hierarchy from anywhere in one line of code by just passing the class type, so the code you'll write will be also decoupled from the view hierarchy itself, for instance:
Navigator.find(MyViewController.self)?.doSomethingSync()
Navigator.navigate(to: MyViewController.self)?.doSomethingSync()
..or you can execute methods asynchronously on the main thread also:
Navigator.navigate(to: MyViewController.self) { (MyViewControllerContainer, MyViewControllerInstance) in
MyViewControllerInstance?.doSomethingAsync()
}
Here the GitHub project link: https://github.com/oblq/Navigator
Related
I am trying to use the new UserNotifications framework for local notifications. I redirect the user to a different viewcontroller when the notification is clicked/open. The notification is not handled properly by UNUserNotificationCenterDelegate didReceive method.
When the notification is in the foreground, and then it is clicked, it redirects to the right viewcontroller, however, when the app is closed and the notification is opened, the app is launched, however, the main viewcontroller is displayed instead.
Problem wasn't actually with the didReceive, but instead with the way the transitions were being made being viewcontrollers, due to methods returning before completion.
I was simulating a normal user flow programmatically. The problem with that is that tableview:didselectRowAt was returning before the performSegue method inside it was executed.
I ended up manually loading the VCs instead and explicitly calling UInavigationController:pushViewController(vc:animated:) to push them on the navigation stack.
I am updating the watch kit support of a client app for Watch OS 2.0.
The iOS app adds a custom action to local notifications that cause the watch to display a custom button if the phone is locked when the local notification fires.
When the user taps the button, the extension delegate sends a message to the phone using the WCSession sendMessage:replyHandler: method.
If the phone is still locked when the user taps the action's button, I would like to display a message to the user saying "please unlock your phone to " (details about "the stuff" are not important.)
However, in WatchKit 2.0, the Extension delegate is a separate critter from interface controllers, and runs on the watch.
All the methods I can find that display an interface controller, like presentAlertControllerWithTitle:message:preferredStyle:actions: are methods of WKInterfaceController.
How do I display a new interface controller from the Extension delegate? I'm trying to figure this out from the docs (and google searching) but so far I've struck out, despite a fairly extensive search.
I had a similar issue when trying to show UI in response to extension delegate messages.
You can get the root controller through [[WKExtension sharedExtension] rootInterfaceController] but there isn't any way to walk the controller hierarchy from the root controller so it isn't really useful if you have other controllers pushed/presented.
I ended up creating a WKInterfaceController subclass that subscribes to NSNotificationCenter on didAppear and unsubscribes on willDisappear which theoretically should mean only one controller (the visible one) would be listening at a time, though I didn't really test it thoroughly enough to guarantee there wasn't any weird corner cases.
The extension delegate sends a notification when receiving a local or remote notification and the notification callback in the interface controller just calls presentAlertControllerWithTitle:... and all my interface controllers descend from that subclass.
I was trying to show an alert when receiving a remote notification while the watch app was open and not in response to the app opening from a notification action though. I'm not sure what order the interface controller didAppear and the extension delegate handleActionWithIdentifier methods would get called in so you may not have any interface controllers listening to the notification when handling the action. If handleAction... gets called first then you might have to add some logic to the interface controller on didAppear to check if there was some pending notification to be shown and have it show it then.
I'm carrating on an app that was written by a programmer before me. It has only 2 view controllers: the main one displaying chat (its the root view controller) and a second one to tinker with your profile. I was asked to implement some kind of notification (preferably one that pops up at the top of the screen) to the user that a message has arrived when they are inside that profile-tinkering view controller. Must I use the APNS server technique, or can I use an easier technique by utilizing the App Delegate somehow?
Use APNS, I prefer the local notification,didReceiveLocalnotification method will get called,then display an alert
Use delegate,assign delegate to the profile controller,and implement the required method,when you have a message arrived,display an alert
When you are inside another view, the APNS wont get displayed because the application is already in foreground.
When app is in foreground and you receive an APNS, didReceiveRemoteNotification method will get called.
You can read APNS package here and notify user of this in a way you want, for e.g. you can display an alert.
According to didReceiveRemoteNotification when in background , we used to be able to handle the user opening the app by clicking the action button on a push notification (or swiping on the push notification, depending on how the user sees push notifications) by implementing -application:didReceiveRemoteNotification: and then checking inside the method whether the application's applicationState was not active.
In iOS 7, there's the new remote-notification background mode, which allows the app to perform background fetch when a remote notification is displayed to the user (without the user necessarily doing anything to the notification). To support this mode, you are supposed to implement the -application:didReceiveRemoteNotification:fetchCompletionHandler: method.
The documentation for -application:didReceiveRemoteNotification: says that if your application delegate implements the application:didReceiveRemoteNotification:fetchCompletionHandler: method, then "the app object calls that method instead of this one." Which means we cannot use -application:didReceiveRemoteNotification: to handle remote notifications anymore, since it's not going to be called.
We should probably put handling logic in application:didReceiveRemoteNotification:fetchCompletionHandler:, but the previous trick for handling it doesn't make sense anymore -- previously, we depended on the fact that the only way for -application:didReceiveRemoteNotification: to be called when the app is not active was if the user tapped the action button on the notification to open the app. However, now, the whole point of the remote-notification background mode is that it can call application:didReceiveRemoteNotification:fetchCompletionHandler: in the background every time a remote notification is received, before the user does anything to it.
So then, how can we now tell when the user opens the app using the action button on the notification?
You still check the application state in application:didReceiveRemoteNotification:fetchCompletionHandler:
UIApplicationStateBackground - App is in the background receiving a push notification
UIApplicationStateInactive - App is opening from the user tapping a notification
I was use this delegate function to add the 『Notification Number』.
Cause our Server not send the Badge to our Clients.
Then I used the strange method to add the 『Notification Number』 with this delegate function, and I also add a code to switch UIViewController in this function.
I found out when I use the server push Notification to my test App, and the status of test App is in the background, even I am using Twitter or Safari.
My test App also switch UIViewController to another UIViewController after I push Notification from the server.
I am using push notifications in my app and I would like to send user to particular view, not the view he last saw. Is it possible?
You need to implement the appropriate AppDelegate messages.
Specifically, you will receive the APNS payload on the application:didFinishLaunchingWithOptions:
You might also receive the payload in a different message, application:didReceiveRemoteNotification: if the application is active.
Then when you know that your app was launched because the user touched a notification, you can direct him to a specific view accordingly.
I don't think that you have control over what the user sees while app is starting app (opening animation). After the app is fully active, you can send him wherever you want to by opening proper view controllers, setting proper tab, etc...