Переход к определенным контроллерам представления из методов AppDelegate

На данный момент я реализовал эти два метода в своем 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 Maps (поскольку это приложение для маршрутизации).

МОЙ ВОПРОС: КАК ЛУЧШЕ ПЕРЕЙТИ К КОНКРЕТНОМУ UIViewController ИЗ APPDELEGATE (независимо от того, в каком представлении находится пользователь)?

Причина, по которой я спрашиваю, заключается в том, что в данный момент я пытаюсь перейти к нему вручную в зависимости от того, где может находиться пользователь. Например, они могут находиться в UIViewController, который отображается модально (которое затем нужно закрыть), или они могут находиться глубоко в UINavigationController, в котором приложению затем нужно будет вызвать popToRootViewController.

Делая это таким образом, код становится волосатым и, похоже, работает неправильно. Также просто не кажется правильным делать это таким образом, потому что он очень хрупкий.


person Mario A Guzman    schedule 27.02.2016    source источник
comment
проверьте этот stackoverflow.com/a/26757245/3535399   -  person vivek takrani    schedule 28.02.2016
comment
@vivektakrani, не совсем то, что я ищу ... это viewDidFinishLaunchingWithOptions ... что происходит только один раз. Я говорю о двух других методах делегирования (упомянутых в моем посте), которые происходят, если пользователь заходит из Apple Maps или Spotlight — оба они могут быть счастливы несколько раз в течение жизни приложения.   -  person Mario A Guzman    schedule 29.02.2016


Ответы (2)


Я просто пытался понять, как реализовать первый упомянутый вами метод, и нашел полезное начало с 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 как? 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.

} 

Это работает для меня, но я должен сделать предостережение. В моем приложении есть только одна раскадровка с тремя viewController'ами (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
}

Этот viewController имеет этот метод:

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)
        }
    }
}
person Ben Patch    schedule 04.03.2016

Я думаю, что хорошим местом для повторной навигации является событие UIApplicationDidBecomeActiveNotification с подпиской в ​​​​контроллере корневого представления (независимо от того, что вы используете).

Когда вы делаете свой код в AppDelegate - просто запланируйте действие: соберите свою посылку с абстрактным количеством свойств, параметров данных и так далее. Сохраните его где-нибудь (NSUserDefauils - хорошее место, но это может быть даже экземпляр SqlCipher). И продолжайте отдыхать с надеждой на следующее событие.

Когда UIApplicationDidBecomeActiveNotification запускается - проснитесь, поймайте сохраненную часть Action и выполните повторную навигацию в соответствии со свойствами Action.

О ваших контроллерах модального представления. Они (точнее - контроллеры, которые показывают ВОЗ) должны быть готовы закрыть все VC, которые они показывают модально, когда наступит событие повторной навигации.

person A. Petrov    schedule 12.05.2020