Present Specific View Controller in Didreceiveremotenotification with Swift

How to Open a Specific View Controller On didReceiveRemoteNotification when application is in back ground

1.Firstly you should Turn On Background Fetch in app "Capabilities"
2. Then use following code in app delegate

In AppDelegate class add following code:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// print(userInfo)
let vc = mainStoryBoard.instantiateViewController(withIdentifier: "destinationVC") as! destinationVC
self.visibleNavController.pushViewController(vc, animated: true)
}

For iOS 10 use following code:
1.Import

 import UserNotifications

For foreground fetch

     @available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (_ options: UNNotificationPresentationOptions) -> Void) {
var userInfo = NSDictionary()
userInfo = notification.request.content.userInfo as NSDictionary
let pay = userInfo as NSDictionary
let driverLocationVC = mainStoryBoard.instantiateViewController(withIdentifier: "destinationVC") as! destinationVC
self.visibleNavController.pushViewController(driverLocationVC, animated: true)

}

For the background

 @available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("Userinfo \(response.notification.request.content.userInfo)")

var userInfo = NSDictionary()
userInfo = response.notification.request.content.userInfo as NSDictionary
print(userInfo)
let driverLocationVC = mainStoryBoard.instantiateViewController(withIdentifier: "DriverLocationVC") as! DriverLocationVC
self.visibleNavController.pushViewController(driverLocationVC, animated: true)
}

For device token fetch

 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print("Got token data! \(tokenString)")

UserDefaults.standard.set(tokenString, forKey: "device_token")
UserDefaults.standard.synchronize()
}

Present specific view controller in didReceiveRemoteNotification with Swift

Try this

let storyboard = UIStoryboard(name: "YourStoryboardName", bundle: nil)
let rootVC = storyboard.instantiateViewControllerWithIdentifier("HomeVC") as! UITabBarController
if PFUser.currentUser() != nil {
rootVC.selectedIndex = 2 // Index of the tab bar item you want to present, as shown in question it seems is item 2
self.window!.rootViewController = rootVC
}

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()
}
}

How to push a view controller from App Delegate on didReceiveRemoteNotification in Swift?

I managed to get it working as I needed with help from both Sh_Khan and the answer I found in this thread: How can I show ViewController in UITabBarController?

My initial view controller is a tabBar and therefore, this is the correct code for me:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

let info = userInfo as NSDictionary
let name: String = info.value(forKey: "view-controller") as! String

switch name {
case "controller1":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let controller1VC = storyboard.instantiateViewController(withIdentifier: "controller1VC") as! Controller1VC
let tabBar = self.window?.rootViewController as? UITabBarController
let nav = tabBar?.selectedViewController as? UINavigationController
nav?.pushViewController(controller1VC, animated: true)
default:
print("Nothing")
}
}

So this code will essentially convert the tabBar to a UINavigationController allowing for a pushViewController to work.

I hope this helps anyone else.

Handle remote notification from within view controller

In your app delegate, do:

  weak var configureiMacViewController: ConfigureiMacViewController?

Create helper functions to keep your code clean and readable:

private func updateiMacImage(_ image: UIImage, in existingViewController: ConfigureiMacViewController) {
existingViewController.image = image
}

private func showiMacImage(_ image: UIImage) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootTabBarController = self.window?.rootViewController as! UITabBarController
let firstNavigationController = storyboard.instantiateViewController(withIdentifier: "initialVC1") as! UINavigationController
rootTabBarController.viewControllers![0] = firstNavigationController

//the viewController to present
let viewController = storyboard.instantiateViewController(withIdentifier: "configureiMac") as! ConfigureiMacViewController
configureiMacViewController = viewController

// present VC
firstNavigationController.pushViewController(viewController, animated: true, completion: {
viewController.image = UIImage(named: "iMac" + iMacConfig)
})
}

Then update:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let data = userInfo["showiMac"] as? [String: String], let iMacConfig = data["iMacConfig"] {
let image = UIImage(named: "iMac" + iMacConfig)
if let existingViewController = configureiMacViewController {
updateiMacImage(image, in: existingViewController)
} else {
showiMacImage(image)
}
completionHandler(.noData)
}
}

The weak var in your AppDelegate will store a reference to your view controller but the "weak" keyword will allow the view controller to be released from memory if it is dismissed, in which case the variable will be nil the next time you try to access it. If the view controller is still visible, then its value will still be defined and you will be able to re-use it to update the image.

You will most likely have to also update your ConfigureiMacViewController code to:

var image: UIImage! {
didSet {
imageView.image = image
}
}

override func viewDidLoad() {
super.viewDidLoad()
imageView.image = image
}

This ensure that if the view controller was already loaded and displayed, but you update the image variable, that the image view is loaded with the most recent image.

Good luck!

Load a specific viewController on push notification Swift 2 AppDelegate

I want to respond to my own question because I think maybe someone is facing the same situation, I have to say thanks to @Muneeba

Well, first of all you have to know if your remote push notification needs to do a background fetch, this is important because if so the didReceiveRemoteNotification is called twice (first when you click on the notification alert, seconds when it opens the app), so you have to be aware of this.

In my case I didn't do a background fetch, so my content-available:false flag was set to false.

Next thing to do is add you desire ["key":value] to the notification payload to know whether you want to open a specific view controller or not.

Manage whether open a view controller or not.

In my app I want to open a alert control pop up always showing the body of the push notification (with a OK button) and only when certain value is set open a alert control with a question to the user whether or not he wants to open the new content that arrives (normally this content is a web based content that open a webview embedded in a view controller)

In the didReceiveRemoteNotification:

if let mensaje = userInfo["m"] as? String {
// Here is where I know if the value is set in the notification payload
let alertCtrl = UIAlertController(title: titulo, message: mensaje as String, preferredStyle: UIAlertControllerStyle.Alert)
if url == nil {
alertCtrl.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
} else {
alertCtrl.addAction(UIAlertAction(title: "Ver receta", style: .Default, handler: {
action in

let storyboard = UIStoryboard(name: "Main", bundle: nil)
//self.window?.rootViewController = storyboard.instantiateViewControllerWithIdentifier("TabbedController") as! UITabBarController
let navigationController = storyboard.instantiateViewControllerWithIdentifier("pushNotificationNavigation") as! UINavigationController
let dVC:NotTestViewController = navigationController.topViewController as! NotTestViewController
// This is for passing the URL to the view Controller
dVC.url = self.url!
self.window?.rootViewController?.presentViewController(navigationController, animated: true, completion: {})

})
)
alertCtrl.addAction(UIAlertAction(title: "Cancelar", style: .Destructive, handler: nil))
}
// Find the presented VC...
var presentedVC = self.window?.rootViewController
while (presentedVC!.presentedViewController != nil) {
presentedVC = presentedVC!.presentedViewController
}
presentedVC!.presentViewController(alertCtrl, animated: true, completion: nil)

handler(UIBackgroundFetchResult.NoData)
}

didReceiveRemoteNotification presentViewController from anywhere when running

Fixed it by changing:

rootViewController.presentViewController(navigationController, animated: true, completion: nil)

to:

rootViewController.visibleViewController!.presentViewController(navigationController, animated: false, completion: nil)

How to get specific view controller on click of local Notification?..I tried all possible way to achieve but couldn't

In AppDelegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler {

UINavigationController *nvc = (UINavigationController *)self.window.rootViewController;

// Currently visible ViewController
UIViewController *vc = nvc.visibleViewController;

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main"
bundle:NULL];
// YourViewController to Push in Your case SecondViewController
yourViewController *myVc= [sb instantiateViewControllerWithIdentifier:@"yourViewController"];

[navigationController pushViewController:myVc animated:true];
}

You can check Particular notification by response.actionIdentifier

in Your case with response.notification.request.content.categoryIdentifier
You check particular Notification

To set catagoryIdentifier

muContent.categoryIdentifier = @"Your_Identifier";

Opening specific view with navigation controller from push notication

What you're doing is completely replacing the root view controller of your application, this means that all the current UI will be discarded.

What you should do instead is to use your knowledge of your application to direct it to the new content. For example, if your root view controller is a navigation controller, you can cast rootViewController to a nav controller and push it (this will fail if your root view controller is something else, like a tab bar controller).

guard let vc = storyboard.instantiateViewController(withIdentifier: "notification") as? NotificationViewController else {
fatalError("Main Storyboard doesn't have a notification controller")
}
guard let nav = self.window?.rootViewController as? UINavigationController else {
return //handle unexpected state
}
nav.push(vc, animated: true)

Another option would be to embed your notification controller into a navigation controller, add a Close button, and present it modally, that way you can present it on top of rootViewController no matter what that controller is.



Related Topics



Leave a reply



Submit