I am trying to perform a segue after getting a notification.
Here is what I have in my app delegate.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let viewController = self.window!.rootViewController!.storyboard!.instantiateViewControllerWithIdentifier("SecondViewController")
self.window?.rootViewController = viewController
}
This takes me directly to the view I would like it to go to, however the navbar and tab bar are hidden. From the app delegate, how do I perform a segue from one view to another? So that I can reach by second view as if I had pushed from my first?
Did you try with:
viewController.performSegueWithIdentifier("my_segue_identifier", sender: nil)
Also the more robust way is to broadcast a NSNotification from your AppDelegate and have your viewcontroller listen for a specific notification.
My solution:
add public variable in AppDelegate (etc. flag =1)
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("User Info = ",response.notification.request.content.userInfo)
flag = 1; <---
completionHandler()
}
and check the flag on rootviewcontroller-> ViewDidLoad. if it's true ? call your spesific segue
override func viewDidLoad() {
super.viewDidLoad()
if (flag == 1) {
self.performSegue(withIdentifier: "roottanBildirimSegue", sender: self)
}
Related
I have researched and came across a few articles about opening local notifications to a specific view and showing the information within the view controller. Unfortunately, I'm still unable to make the function work in my app.
I have a quote app and I send local and push notifications. When I have a scheduled notification, the user should be able to click the notfication and be directed to the "TopViewController" and the controller should display the notification information. Instead the app opens up to the last view controller the user was on.
Could someone tell me what I am doing wrong?
Here is the code the I have in the "TopViewController" ViewDidLoad
NotificationCenter.default.addObserver(self, selector: ("Scheduled:"), name:NSNotification.Name(rawValue: "Scheduled"), object: nil)
Here is the code I have in the AppDelegate:
#Published var quote = Quote(id: "", text: "", author: "")
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let application = UIApplication.shared
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
}
guard let rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
return
}
print("got active scene")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let conversationVC = storyboard.instantiateViewController(withIdentifier: "TopViewController") as? TopViewController,
let tabBarController = self.window?.rootViewController as? UITabBarController
{
conversationVC.shareQuote?.text = response.notification.request.content.body
conversationVC.shareQuote?.author = response.notification.request.content.subtitle
}
completionHandler()
}
The notification doesn't open up to the right view controller nor does it show the notification information.
Here are a few ideas I have, however, I cannot be certain if this is your fix but it was too much to put into the comments.
Are you setting the app delegate as the UNNotificationCenter's delegate ?
UNUserNotificationCenter.current().delegate = self
Does anything print to your console like print("got active scene") or print("user tapped the notification bar when the app is in foreground") ?
If you have done both of the above, can you add breakpoints inside this block of code
{
conversationVC.shareQuote?.text = response.notification.request.content.body
conversationVC.shareQuote?.author = response.notification.request.content.subtitle
}
This will tell you if there is some issue in your logic if it does not enter this block of code
Update
To manage notifications in the foreground, you need to also implement this UNUserNotificationCenterDelegate method:
// This will show the notification when the app is in
// the foreground. This is optional
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.list, .banner, .badge, .sound])
}
I have so many screens in my application. So when the user taps on the local notification , I'd like to deep-link one of the screens.
The could be not running or active on one of those screens or inactive or suspended state.
I couldn't see how to do that
If anyone could explain it'd be great
You can use DeepLinkKit for navigation to different screens. I'm using this library in my app, I have about 30-37 deeplinks for every screen in the app. I'm using this with Cordinators pattern for navigation. Let me know if you need any help with implementing.
Send Notification from anywhere.
func sendNotification(){
let info: [String: String] = ["vc_name": "CartViewController"]
NotificationCenter.default.post(name: Notification.Name("YourLocalNotification"), object: nil, userInfo: info)
}
Add Notification handler on Receive Notification in your root controller.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.youNotificationAction(notification:)), name: Notification.Name("YourLocalNotification"), object: nil)
}
Receive notification, Check your notified information and navigate to your respective controller.
#objc func youNotificationAction(notification: Notification) {
if let vcName = notification.userInfo?["vc_name"] as? String {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let toVC = storyBoard.instantiateViewController(withIdentifier: vcName)
navigationController?.pushViewController(toVC, animated: true);
}
}
Inherit UNUserNotificationCenterDelegate in appdelegate or viewcontroller
Implement below methods
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(UNNotificationPresentationOptions.alert)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
completionHandler()
}
This is where you intercept the notification tap and call the appropriate modules either using OpenURL or doing a direct push or present or switch the tab of viewcontroller.
My app allows remote push notifications to a user. How do I enable it to be opened in a specific view controller when the user taps on the push notification? I want the app to open and navigate to a specific view controller depending on the push notification received.
you have to check when your app is on close state using launch option in " func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool{ :
if let option = launchOptions {
let info = option[UIApplication.LaunchOptionsKey.remoteNotification]
if (info != nil) {
self.goAnotherVC()
}
}
and in view did load in your landing VC set the observer
NotificationCenter.default.addObserver(self, selector: #selector(self.goToVc(notification:)), name:NSNotification.Name(rawValue:identifier), object: nil)
Selector Method :
#objc func goToVc(notification:Notification) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier:"landingVC") as! landingVC
self.navigationController?.pushViewController(vc, animated: true)
}
In app delegate :
func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
NotificationCenter.default.post(name:NSNotification.Name(identifier), object: userInfo)
}
This answer is for iOS 13+
In AppDelegae :
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
NotificationCenter.default.post(name: NSNotification.Name(identifier), object: nil)
completionHandler()
}
In viewDidLoad of Landing ViewController :
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.showChatController(notification:)), name:NSNotification.Name(rawValue: "noti"), object: nil)
}
In your landing viewController add following selector method :
#objc
func showChatController(notification: Notification) {
print("DEBUG: show chat controller here..")
}
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
If the user clicks on the icon, then the application starts with the start page. How can I make sure that the user clicked on the push notification to launch the application with another start page?
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken;
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Registration failed!")
}
// Firebase notification received
// This function will work app is in foreground state
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
// custom code to handle push while app is in the foreground
if notification.request.content.userInfo["cook"] != nil{
return;
}
print(notification.request.content.userInfo)
UIApplication.shared.applicationIconBadgeNumber = 1;
DispatchQueue.main.async {
// add some code here..
// window?.rootViewController = LoginController()
// If you use the storyboard, then you can get controller by
// storyboard?.instantiateViewController(withIdentifier: "identifier") as! UIViewController
}
}
// This function will work app is in state of background or closed.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// if you set a member variable in didReceiveRemoteNotification, you can check if this is from closed or background
print("Handle push from background or closed\(response.notification.request.content.userInfo)")
if response.notification.request.content.userInfo["somevariable"] != nil{
return;
}
UIApplication.shared.applicationIconBadgeNumber = 1;
DispatchQueue.main.async {
// add some code here..
}
}
Please use this this code into AppDelegate.swift
Please see the function called userNotificationCenter and comments in
code.
Ok..i will make it simple for you.
First step-
Add this function inside your AppDelegate file.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Hi Kirill...")
}
If you add this in your AppDelegate file, after running your app when you tap on the notification you will see this on your debugger, .
Like this -
And finally, to show a specific page in application add this inside the function.
let sb = UIStoryboard(name: "Main", bundle: nil)
let otherVC = sb.instantiateViewController(withIdentifier: " Your view controller identifier name") as! yourViewControllerClassName
window?.rootViewController = otherVC;
It will look like this -
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Hi Kirill...")
let sb = UIStoryboard(name: "Main", bundle: nil)
let otherVC = sb.instantiateViewController(withIdentifier: " Your view controller identifier name") as! yourViewControllerClassName
window?.rootViewController = otherVC;
}
Make sure you add a another viewController, what you want to redirect/show when you tap on the notification. Thank you.
I have an iOS APP and a push notifications system which sends programatically notifications to the storing their token in a database.
I have some views which I show or hide in the default View Controller. I would like to make the APP show a specific view when the user taps the notification. I have created a function, but I dont know how to make it work.
You can catch a push notifications inside AppDelegate and add Observer inside your controller file where you want to show a specific view on tap.
Send push notification payload data in userInfo or object in NotificationCenter.default.post.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
UIApplication.shared.applicationIconBadgeNumber = 0
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "NewNotification") , object: nil, userInfo: response.notification.request.content.userInfo)
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(.alert)
}
Add Notification Observer in your controller file :
NotificationCenter.default.addObserver(self, selector: #selector(pushNotificationHandler(_:)) , name: NSNotification.Name(rawValue: "NewNotification"), object: nil)
then call UI update method :
func pushNotificationHandler(_ notification : NSNotification) {
// self.udateUI() // Add code to show a specific view on tap.
}
In AppDelegate APNS delegate method make a check according to the userInfo you get with your notification/payload and then call that function either
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
if response.notification.request.content.userInfo["ViewType"] as! String == "ShowNotificationView" {
// Then you can implement your functionaliton here according to the need.
}
if you need any other help please let me know by posting the actuall code & requirement over
First of all, it is required to add one more key to the push notification payload as screen_type based on the content to which screen you need to navigate or show the particular view controller(screen).
After that, add the following method to your AppDelegate class which implements the notifications handler
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
let payload = userInfo
let type = payload["type"]
if type == "all-posts" || type == "default"{
/*
* I'm assuming you have your own HomeViewController object
*/
let homeVC = HomeViewController()
// present or push
UIApplication.topViewController()?.present(homeVC, animated: true, completion: nil)
}else if type = "post-details"{
/*
* I'm assuming you have your own PostDetailViewController object
*/
let postDetailVC = PostDetailViewController()
// present or push
UIApplication.topViewController()?.present(postDetailVC, animated: true, completion: nil)
}else if type == "friend-request"{
/*
* I'm assuming you have your own UserViewController object
*/
let userVC = UserViewController()
// present or push
UIApplication.topViewController()?.present(userVC, animated: true, completion: nil)
}
}
Helper method
extension UIApplication {
class func topViewController(base: UIViewController? = (UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(base: selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
Note: If you are using latest version of swift, you are required to implement the UNUserNotificationCenterDelegate methods