0

I want to call a UIViewController with NavigationController designed in Storyboard programmatically when I select a dynamic shortcut.

I designed my UIViewController and its NavigationController in Main.storyboard and I put a storyboard ID (I called it MyUICtrlStoryID)

In order to create my dynamic shortcut I wrote the following code in the AppDelegate:

@available(iOS 9.0, *)
    func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: Bool -> Void) {




        let handledShortCutItem = shortcutItem.type // handleShortCutItem(shortcutItem)

        if handledShortCutItem == "3DTouchShourtcutID"{

            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

            let storyboard = UIStoryboard(name: "Main", bundle: nil)

//FirstViewcontroller UI will be called as root UIView
            let initialViewControlleripad : FirstViewController = storyboard.instantiateViewControllerWithIdentifier("FirstViewControllerID") as! FirstViewController



            initialViewControlleripad.go2MySecondUI = true   //set this check variable in order to launch my second UI View from the first one.

            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
            self.window?.rootViewController = initialViewControlleripad
            self.window?.makeKeyAndVisible()
        }
      }

in the viewWillAppear function of my FistViewController

if #available(iOS 9.0, *) {

                let shortcutItem = UIApplicationShortcutItem(type: "3DTouchShortcutID",
                    localizedTitle:    "This action",
                    localizedSubtitle: "action description",
                    icon: UIApplicationShortcutIcon(type: UIApplicationShortcutIconType.Add),
                    userInfo: nil)


                UIApplication.sharedApplication().shortcutItems = [shortcutItem]

                //check if FirstViewControler had to call the second UI 
                if go2MySecondUI == true {
                    self.go2MySecondUI = false


                            let newViewCtrl = self.storyboard?.instantiateViewControllerWithIdentifier("MyUICtrlStoryID") as? SecondViewController
                           // call second UI view

                   dispatch_async(dispatch_get_main_queue()) {
                       self.presentViewController(newViewCtrl!, animated: true, completion: nil)
                   }
                                              //  }
                }

This code works fine: when I select, by 3d touch, my shortcut, my secondviewcontroller will be call and its UIView will be showed .. but without its navigation controller. otherwise if I call my secondUIcontroller by a button designed in storyboard (with related segue callback) the secondUIView will be showed with navigation controller correctly..

What is wrong?

5
  • Why are you pushing the view controller then presenting the same view controller? self.navigationController?.pushViewController(newViewCtrl!, animated: true) dispatch_async(dispatch_get_main_queue()) { self.presentViewController(newViewCtrl!, animated: true, completion: nil) } Commented Jan 12, 2016 at 15:40
  • @beyowulf : Uh I'm sorry! I forget to remove it .. but, of course, it doen't resolve my problem :S Commented Jan 12, 2016 at 15:56
  • push don't present (i.e. delete dispatch_async(dispatch_get_main_queue()) { self.presentViewController(newViewCtrl!, animated: true, completion: nil) } and just say self.navigationController?.pushViewController(newViewCtrl!, animated: true) make sure self.navigationController is not nil. Even better might be to just call self.preformSegueWithIdentifier Commented Jan 12, 2016 at 16:04
  • @beyowulf unfortunately if I use self.navigationController?.pushViewController(newViewCtrl!, animated: true) it will not work . Moreover, in Swift 2.1, you have to use dispatch_async(dispatch_get_main_queue()) Commented Jan 12, 2016 at 18:22
  • You want to know why the view controller is not in a navigation controller. It is because you are presenting it modally. You need to say something like self.navigationController.pushViewController or self.navigationController.showViewController. This will only work if firstViewController is itself embedded in a navigationController. If fine to dispatch to the main queue but is only necessary if the method might be called from a different thread which viewWillAppear will not. Commented Jan 12, 2016 at 19:36

1 Answer 1

1

You need to embed your first view controller in a UINavigationController. So in the AppDelegate your code should be:

@available(iOS 9.0, *)
    func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: Bool -> Void) {




        let handledShortCutItem = shortcutItem.type // handleShortCutItem(shortcutItem)

        if handledShortCutItem == "3DTouchShourtcutID"{

            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

            let storyboard = UIStoryboard(name: "Main", bundle: nil)

//FirstViewcontroller UI will be called as root UIView
            let initialViewControlleripad : FirstViewController = storyboard.instantiateViewControllerWithIdentifier("FirstViewControllerID") as! FirstViewController



            initialViewControlleripad.go2MySecondUI = true   //set this check variable in order to launch my second UI View from the first one.
            let navigationController = UINavigationController(rootViewController: initialViewControlleripad)

            self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
            self.window?.rootViewController = navigationController
            self.window?.makeKeyAndVisible()
        }
      }

Then in viewWillAppear of the FirstViewController you need to push the second view controller rather than present. So your code should read:

if #available(iOS 9.0, *) {

                let shortcutItem = UIApplicationShortcutItem(type: "3DTouchShortcutID",
                    localizedTitle:    "This action",
                    localizedSubtitle: "action description",
                    icon: UIApplicationShortcutIcon(type: UIApplicationShortcutIconType.Add),
                    userInfo: nil)


                UIApplication.sharedApplication().shortcutItems = [shortcutItem]

                //check if FirstViewControler had to call the second UI 
                if go2MySecondUI == true {
                    self.go2MySecondUI = false


                            let newViewCtrl = self.storyboard?.instantiateViewControllerWithIdentifier("MyUICtrlStoryID") as? SecondViewController
                           // call second UI view

                           self.navigationController?.pushViewController(newViewCtrl, animated: true)

                                              //  }
                }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.