从AppDelegate方法导航到特定的视图控制器

6

目前,我已经在我的AppDelegate中实现了这两种方法

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool

并且。
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool

如果用户通过 Spotlight 的搜索结果打开我的应用程序,则将调用第一个函数,如果我的应用程序从 Apple 地图中打开(因为它是一款导航应用程序),则将调用第二个函数。

我的问题是,独立于用户处于哪个视图之下,从 APPDELEGATE 跳转到特定的 UIViewController 的最佳方法是什么?

我提出这个问题的原因是因为目前我正在尝试手动导航到该视图控制器,具体取决于用户可能在哪里。例如,他们可能在以模态形式显示的 UIViewController 中(然后需要关闭它),或者他们可能深入了一个 UINavigationController,在这种情况下,应用程序将需要调用 popToRootViewController

以这种方式处理,代码变得复杂且似乎不正常。这样做也不正确,因为它非常脆弱。


请查看此链接:https://dev59.com/E18d5IYBdhLWcg3wgiX4#26757245 - vivek takrani
@vivektakrani,不完全是我要找的... 这些是viewDidFinishLaunchingWithOptions... 只会发生一次。 我在谈论另外两个委托方法(在我的帖子中提到),如果用户从Apple Maps或Spotlight进入,则会发生这些情况 - 在应用程序的生命周期中都可以发生多次。 - Mario A Guzman
2个回答

0

我刚试图弄清楚如何实现你提到的第一种方法,并从https://www.hackingwithswift.com/read/32/4/how-to-add-core-spotlight-to-index-your-app-content找到了一个有用的起点。 他的代码是:

func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
    if userActivity.activityType == CSSearchableItemActionType {
        if let uniqueIdentifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String {
            let splitViewController = self.window!.rootViewController as! UISplitViewController
            let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController

            if let masterVC = navigationController.topViewController as? MasterViewController {
                masterVC.showTutorial(Int(uniqueIdentifier)!)
            }
        }
    }

    return true
}

我发现self.window?.rootViewController as? yourRootViewControllerClass是你问题的好起点。

我的代码非常基础,看起来像这样:

// create a storyBoard item to instantiate a viewController from. If you have multiple storyboards, use the appropriate one. I just have one so it is "Main"
let sb = UIStoryboard(name: "Main", bundle: nil)

// get the navigation controller from the window and instantiate the viewcontroller I need.
if let viewController = sb.instantiateViewControllerWithIdentifier("DetailViewController") as? ViewController,
let nav = window?.rootViewController as? UINavigationController {

    viewController.setupController(bookName)// setup the viewController however you need to. I have a method that I use (I grabbed the bookName variable from the userActivity)
    nav.pushViewController(viewController, animated: false)//use the navigation controller to present this view.

} 

这对我来说是有效的,但我必须提出一个警告。我的应用程序只有一个故事板,其中包含三个视图控制器(NavController->tableViewController->ViewController)。我不确定这种逻辑在更复杂的应用程序中如何工作。
另一个很好的参考资料是:http://www.appcoda.com/core-spotlight-framework/
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
    let viewController = (window?.rootViewController as! UINavigationController).viewControllers[0] as! ViewController
viewController.restoreUserActivityState(userActivity)

    return true
}

那个视图控制器有这个方法:

override func restoreUserActivityState(activity: NSUserActivity) {
    if activity.activityType == CSSearchableItemActionType {
        if let userInfo = activity.userInfo {
            let selectedMovie = userInfo[CSSearchableItemActivityIdentifier] as! String
            selectedMovieIndex = Int(selectedMovie.componentsSeparatedByString(".").last!)
            performSegueWithIdentifier("idSegueShowMovieDetails", sender: self)
        }
    }
}

0

我认为重新导航的好地方是在事件UIApplicationDidBecomeActiveNotification中,可以在根视图控制器(无论您使用什么)中进行订阅。

当您在AppDelegate中编写代码时,只需安排一个操作:使用抽象数量的属性、数据参数等组装您的包裹。将其存储在某个地方(NSUserDefauils是一个不错的选择,但甚至可以是SqlCipher实例)。然后希望遵循事件的其余部分。

当触发UIApplicationDidBecomeActiveNotification时,唤醒,捕获存储的操作包裹,并根据操作属性执行重新导航。

关于您的模态视图控制器。它们(确切地说是显示的控制器)应该准备好在重新导航事件到达时解除显示所有VC。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接