Переход к ViewController из AppDelegate, запускаемого UIApplicationShortcutItem

В моем приложении первое запущенное представление контролируется RootUIViewController, Теперь пользователь может нажать на любую из кнопок в этом представлении, а затем segue на вид, контролируемый LeafUIViewController, Каждая кнопка указывает на одно и то же представление с разными значениями для некоторых аргументов.

Теперь я реализовал контекстное меню 3D Touch, которое правильно вызывает следующую функцию в AppDelegate:

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void)

В этой функции я хочу перейти к LeafUIViewController так что пользователь все еще может вернуться к RootViewController,

Как правильно сделать это так, чтобы Root правильно создавался, помещался в стек и затем просматривал навигацию к Листу?

1 ответ

Решение

Я не рекомендую делать какие-либо действия по запуску определенных переходов от этого обратного вызова. Я обычно устанавливаю глобальное состояние и обрабатываю его во всех соответствующих контроллерах представления. Они обычно всплывают на главном viewcontroller. Там я делаю действия программно, как обычно делает пользователь.

Преимущество состоит в том, что иерархия viewcontroller инициализируется обычным способом. Состояние может затем обрабатываться первым viewcontroller, который будет отображаться на экране, который не обязательно является первым viewcontroller приложения. Приложение может быть уже инициализировано, когда пользователь запускает действие. Таким образом, в иерархии может быть случайный view-контроллер.

Я использую что-то вроде:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    if #available(iOS 9.0, *) {
        if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
            handleShortcutItem(shortcutItem)
        }
    }
    return true
}

enum ShortcutType: String {
    case myAction1 = "myAction1"
    case myAction2 = "myAction2"
}

@available(iOS 9.0, *)
func handleShortcutItem(shortcutItem: UIApplicationShortcutItem) -> Bool {

    if let shortcutType = ShortcutType.init(rawValue: shortcutItem.type) {

        switch shortcutType {
            case .myAction1:
                MyHelper.sharedInstance().actionMode = 1
                return true
            case .myAction2:
                MyHelper.sharedInstance().actionMode = 2
                return true
            default:  
               return false
        }
    }
    return false
}

а затем в main viewController (например, в главном меню) обработать действие как-то:

override func viewDidAppear() {
    super.viewDidAppear()
    switch MyHelper.sharedInstance().actionMode {
            case 1:
                // react on 1 somehow - such as segue to vc1
            case 2:
                // react on 2 somehow - such as segue to vc2
        default:  
            break
    }
    // clear the mode
    MyHelper.sharedInstance().actionMode = 0
}

И в других ВК:

override func viewDidLoad() {
    super viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "reloadView", name: UIApplicationWillEnterForegroundNotification, object: nil)
}

func reloadView() {
    if MyHelper.sharedInstance().actionMode {
        self.navigationController.popToRootViewControllerAnimated(false) 
    }
}

Это может быть не лучшим, если вы используете несколько VC. Если есть что-то лучше, я бы хотел узнать это:)

Другие вопросы по тегам