0

when the user opening the push notification i present view from appdelget by this code

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

    application.applicationIconBadgeNumber = 0; // Clear badge when app is launched
    if UserDefaults.standard.bool(forKey: "PushOFF") == false
    {
        registerForRemoteNotification()
    }
    else
    {
        UIApplication.shared.unregisterForRemoteNotifications()
    }
    return true
}
func registerForRemoteNotification()
{
    if #available(iOS 10.0, *)
    {
        let center  = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil{
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    else
    {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    var token = ""
    for i in 0..<deviceToken.count {
        token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
    }
    print("DEVICE TOKEN = \(token)")
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
{
    print("Registration failed! error=\(error)")
}
//Called when a notification is delivered to a foreground app.
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
{
    print("foreground User Info = ",notification.request.content.userInfo)
    completionHandler([.alert, .badge, .sound])
    print("foreground app",notification.request.content.userInfo)
}

//Called to let your app know which action was selected by the user for a given notification.
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
{

    completionHandler()
    let result = response.notification.request.content.userInfo as! Dictionary<String, AnyObject>
    print("action User Info = ",result)

    let app = result["aps"] as! Dictionary<String, AnyObject>
    let title = app["alert"] as! String
    let id = result["id"]?.integerValue
    print("alert=",title,"id=",id!)
    if id != 0
    {
        if UserDefaults.standard.bool(forKey: "login")
        {
            UserDefaults.standard.set(title, forKey: "notificationTitle")
            UserDefaults.standard.set(id, forKey: "notificationId")
            UserDefaults.standard.synchronize()
            if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PostVC") as? UINavigationController
            {
                    var currentController = window?.rootViewController
                    while let presentedController = currentController?.presentedViewController
                    {
                        currentController = presentedController
                    }
                    currentController?.present(controller, animated: true, completion: nil)
            }
        }
    }
}

if the application is working the code run perfect but when the application is off it present "PostVC" view first and present the root-view on top of "PostVC" view!! so you can't see the "PostVC" view.

what is wrong ? but i wouldn't to use window?.makeKeyAndVisible()

bero
  • 13
  • 4
  • What method Is used to show "PostVC" ? – Oleg Gordiichuk Mar 02 '17 at 10:30
  • Possible duplicate of [Opening view controller from app delegate using swift](http://stackoverflow.com/questions/30592521/opening-view-controller-from-app-delegate-using-swift) – Mannopson Mar 02 '17 at 10:37
  • @OlegGordiichuk in the first line in the code ' if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PostVC") as? UINavigationController ' – bero Mar 02 '17 at 12:56
  • @Mannopson i wouldn't to use 'window?.makeKeyAndVisible()' because I wouldn't to have many UIWindows in my app at one time. – bero Mar 02 '17 at 12:59
  • @bero You shouldn't create a new window. Change your rootViewController – Mannopson Mar 02 '17 at 13:02
  • @Mannopson How ? can you help me please ? – bero Mar 02 '17 at 13:04
  • Are you checked my first comment? This is exactly what you need for this case – Mannopson Mar 02 '17 at 13:09
  • @Mannopson the first answer at http://stackoverflow.com/questions/30592521/opening-view-controller-from-app-delegate-using-swift by Kirit Modi : The app will create a new window! second answer by iDhaval the same solution Third answer by Quy Bui the same problem with my code when the app off it present "PostVC" view first and present the rootview on top of "PostVC" view!what solution is right ? – bero Mar 02 '17 at 13:25
  • Yes! It's works – Mannopson Mar 02 '17 at 13:40
  • @bero Are you tested? – Mannopson Mar 02 '17 at 14:29
  • @Mannopson too times and it's didn't work :( – bero Mar 02 '17 at 15:08
  • @bero What did you tried? – Mannopson Mar 02 '17 at 15:11
  • @Mannopson i edited the code in the question. – bero Mar 02 '17 at 15:23
  • Looks like you're tried to open a specific view controller from the delegate method of UserNotifications framework. Right? – Mannopson Mar 02 '17 at 15:51
  • @Mannopson right and it's working fine when the app is running and the user touch the notification but when the app is closed and the user touch the notification the app will open the specific view after that will open the initial view on top so the user will see the initial view only!! – bero Mar 02 '17 at 17:41
  • You can open your desired view controller from didFinishLaunching method. – Mannopson Mar 03 '17 at 05:02
  • @Mannopson Okay, what will happen when the application is running and the user will get push notification ? i think nothing will happen when the user touch the notification ! – bero Mar 05 '17 at 08:14
  • Of course! If you've not implemented the delegate method. You can do something like that by handling the notification action. I think the default action identifier helpful for you. – Mannopson Mar 05 '17 at 08:37
  • @Mannopson Can you tell me how ? because i'm new :( ,Thank you so much for your helps. – bero Mar 05 '17 at 08:50
  • @bero Ok, but not now! Remember: If you want to open a specific view controller whenever notification is pushed? Do not open the modally presented view controller, always open the child view controller instead. – Mannopson Mar 05 '17 at 09:11
  • @Mannopson Okay take your time and Thanks again for your helps. You are awesome. – bero Mar 05 '17 at 09:19

1 Answers1

0

Ok! I give you an idea. Whenever the notification is fired and the user taps the notification, UNNotificationDefaultActionIdentifier will be called. Try this:

 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    switch response.actionIdentifier {

    case UNNotificationDefaultActionIdentifier:

        DispatchQueue.main.async(execute: {
            openViewController()
        })

    default:
        break
    }

    completionHandler()
}

This is going to be your function:

func openViewController() {
    let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PostVC") as? UINavigationController
    self.window?.rootViewController = controller
    self.window = UIWindow.init(frame: UIScreen.main.bounds)
    self.window?.makeKeyAndVisible()
}

But as I suggested above open a childViewController instead.

 func openViewController() {

    let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
    let rootViewController = storyboard.instantiateViewController(withIdentifier: "YourRootViewControllerIdentifier") as! UINavigationController
    let childViewController = storyboard.instantiateViewController(withIdentifier: "YourChildViewControllerIdentifier") as! YourCustomChildViewController

    rootViewController.pushViewController(childViewController, animated: true)

    self.window?.rootViewController = rootViewController
    self.window = UIWindow.init(frame: UIScreen.main.bounds)
    self.window?.makeKeyAndVisible()
}

I have not tested yet. Let me know if it's works! Good luck

Mannopson
  • 2,634
  • 1
  • 16
  • 32
  • i used this function `func openViewController() { let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PostVC") as? UINavigationController self.window?.rootViewController = controller self.window = UIWindow.init(frame: UIScreen.main.bounds) self.window?.makeKeyAndVisible() }` but it's open another UIWindow so i have 2 UIWindow and the same problem when the app is closed so i can see the initial view only again, But i replaced this function by – bero Mar 07 '17 at 11:55
  • `func openViewController() { if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PostVC") as? UINavigationController { if let window = self.window, let rootViewController = window.rootViewController { var currentController = rootViewController while let presentedController = currentController.presentedViewController { currentController = presentedController } currentController.present(controller, animated: true, completion: nil) } } }` – bero Mar 07 '17 at 11:57
  • Now it's working perfect finally :D so i don't know how to thank you for your helps . Thank you so much. – bero Mar 07 '17 at 12:08
  • @bero Therefore I recommended open a child view controller – Mannopson Mar 08 '17 at 00:55