подготовить переключение с помощью UINavigationController ... лучший способ? - PullRequest
0 голосов
/ 24 мая 2018

У меня есть пара segues, представляющих контроллеры модального представления.

class ProfileViewController: UIViewController {
    func configure(profile: Profile) { 
        // Some ProfileViewController specific config
    }
}

class SettingsViewController: UIViewController {
   func configure(settings: Settings) { 
        // Some SettingsViewController specific config
    }
}

Итак, вот некоторый довольно стандартный код, который мы все написали много раз ...

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let nav as UINavigationController:
        switch nav.topViewController {
        case let pvc as ProfileViewController:

            pvc.configure(profile: profile)
        case let svc as SettingsViewController:

            svc.configure(settings: settings)
        default:
            break
        }
    default:
        break
    }
}

Я такжепопробовал это так ...

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let nav as UINavigationController
        where nav.topViewController is ProfileViewController:

        (nav.topViewController as! ProfileViewController).configure(profile: profile)
    case let nav as UINavigationController
        where nav.topViewController is SettingsViewController:

        (nav.topViewController as! SettingsViewController).configure(settings: settings)
    default:
        break
    }
}

Но то, что я хотел бы сделать, - это сочетание двух ...

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.destination {
    case let nav as UINavigationController
        where let pvc = nav.topViewController as ProfileViewController:

        pvc.configure(profile: profile)
    case let nav as UINavigationController
        where let svc = nav.topViewController as SettingsViewController:

        svc.configure(settings: settings)
    default:
        break
    }
}

, но, очевидно, это не скомпилируется.Кто-нибудь сталкивался с лучшим шаблоном для этого?


ОБНОВЛЕНИЕ

Расширяя ответ @ Сержа ниже…

extension UIStoryboardSegue {
    var destinationNavTopViewController: UIViewController? {
        return (destination as? UINavigationController)?.topViewController
    }
}

затем

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch (segue.destination, destinationNavTopViewController) {
    case let (_, pvc as ProfileViewController):

        pvc.configure(profile: profile)
    case let (_, svc as SettingsViewController):

        svc.configure(settings: settings)
    case let (ovc as OtherViewController, _):
        ovc.configure…
    default:
        break
    }
}

1 Ответ

0 голосов
/ 24 мая 2018

Задавая этот вопрос с практическими рекомендациями, мы можем рассмотреть два случая:

  1. Конкретный вариант использования того, чего вы хотите достичь
  2. Более общий вариант использования switch операторы

Теперь для конкретного случая использования кажется, что вы хотите действовать только при включении segue.destination, когда у вас есть контроллер навигации.Вы можете легко достичь этого с помощью if let или guard let, как показано ниже:

guard let navigationController = segue.destination as? UINavigationController else { return }
guard let topController = navigationController.topViewController else { return }
switch topController {
  case let profileViewController as ProfileViewController:
    print("Do something for profile view controller")
  default:
    break
}

Теперь второй случай, который является более общим и о том, как иметь возможность использовать обе переменные в операторе switch.,Ответ кортежей.Например, я приведу пример из документации Apple, а затем приведу пример для вашего конкретного варианта использования.

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of \(x)")
case (0, let y):
    print("on the y-axis with a y value of \(y)")
case let (x, y):
    print("somewhere else at (\(x), \(y))")
}

Теперь приведем пример того, как достичь вышеупомянутого варианта использования.предупредил, что уродливый пример может быть улучшен, но суть в следующем:

switch (segue.destination, (segue.destination as? UINavigationController)?.topViewController) {
case (let nav as UINavigationController, let viewController as ProfileViewController):
    return
// Maybe the destination wasn't a nav maybe it was the sign in view controller and you don't care about the second variable
case (let signInController as SignInViewController, let _):
    return
default:
    return
}

Это сила операторов switch, позволяющих так легко переключать Tuple.Я надеюсь, что мой пример отвечает на ваш вопрос.Я попытался охватить все части вопроса со всеми неясностями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...