iosswift3dtouchquickaction

3D touch quick actions preview view controller only one time


I have the following issue. When I run my app on my phone, 3d touch the icon and select the quick action it launches the app presenting the correct view controller but when I put the app in background and try to invoke the quick action it just opens the app where I have left it. So to make it work I have to kill my app every time. Here is my code:

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
    if shortcutItem.type == "com.traning.Search" {

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

        let searchVC = sb.instantiateViewControllerWithIdentifier("searchVC") as! UINavigationController

        let root = UIApplication.sharedApplication().keyWindow?.rootViewController
        root?.presentViewController(searchVC, animated: false, completion: { () -> Void in
            completionHandler(true)
        })

    }
}

Thanks in advance.


Solution

  • I'm guessing you're trying to present a view controller from a view controller that's not visible. You can use extensions like:

        extension UIViewController {
        func topMostViewController() -> UIViewController {
            if self.presentedViewController == nil {
                return self
            }
            if let navigation = self.presentedViewController as? UINavigationController {
                return navigation.visibleViewController.topMostViewController()
            }
            if let tab = self.presentedViewController as? UITabBarController {
                if let selectedTab = tab.selectedViewController {
                    return selectedTab.topMostViewController()
                }
                return tab.topMostViewController()
            }
            return self.presentedViewController!.topMostViewController()
        }
    }
    
    extension UIApplication {
        func topMostViewController() -> UIViewController? {
            return self.keyWindow?.rootViewController?.topMostViewController()
        }
    }
    

    You can place both of these in your app delegate.swift, above your app delegate class, to get the currently visible view controller.enter image description here Then present the search view controller on that. For example:

    func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
        if shortcutItem.type == "com.traning.Search" {
    
            let sb = UIStoryboard(name: "Main", bundle: nil)
    
            let searchVC = sb.instantiateViewControllerWithIdentifier("searchVC") as! UINavigationController
    
            let topViewController = UIApplication.sharedApplication.topMostViewController()
            topViewController.presentViewController(searchVC, animated: false, completion: { () -> Void in
                completionHandler(true)
            })
    
        }
    }