Как перемещаться и передавать данные между UIViewControllers, макет которых напоминает fork?

#ios #swift #uiviewcontroller #uinavigationcontroller #uikit

#iOS #swift #uiviewcontroller #uinavigationcontroller #uikit

Вопрос:

У меня есть пара UIViewControllers подобных показанных

Макет Fork

Я хочу передать данные из B в C, а также выполнить этот переход. До сих пор я предлагал 2 возможных решения:

  1. Создайте новый экземпляр класса C UIViewController (и сохраните ссылку на данные в нем), извлеките B из navigation controller и вставьте C в него.
  2. Отправьте данные в A, извлеките B из navigation controller , а затем в viewWillAppear методе A проверьте, не равны ли данные нулю, чтобы узнать, следует ли отправлять их в C и выполнять segue .

Должен ли я использовать любой из этих 2 подходов? Или есть более элегантное / правильное решение для этой ситуации?

Спасибо

Комментарии:

1. Это собственный контроллер просмотра

2. Я не понимаю. A подталкивает к B? И с B вы хотите перейти на C?

3. Сценарий заключается в том, что я перешел от A к B, и теперь я хочу перейти от B к C, но также передать некоторые данные

4. Вы уже приняли ответ, но в дальнейшем постарайтесь быть более точным с вашим языком. Переход от A к B, а затем переход от B к C ничего не значит. Вы нажимаете или представляете? Является ли A родительским для B и C, и вы переходите между дочерними элементами? Является ли A собственным контроллером просмотра, и пользователь может нажать на B или C? Сейчас это не имеет значения, но изучите терминологию, это очень поможет.

Ответ №1:

Организуйте диспетчер данных родительского контроллера или используйте Core Data.

В случае хранения данных в родительском контроллере используйте внедрение зависимостей, как описано здесь

Вот пример для вашего случая:

 var dataFromC = "" // or nil
var dataFromB = "" // or nil

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "B",
        let viewController = segue.destinationViewController as? BViewController {
        viewController.dataFromC = self.dataFromC

//           declare method in BViewController
//           var method : ((String) -> ())? = nil
        viewController.method = {[weak self] valueFromB in
            self?.dataFromB = valueFromB
        }
    }

    if segue.identifier == "C",
        let viewController = segue.destinationViewController as? CViewController {
        viewController.dataFromB = self.dataFromB

//           declare method in CViewController
//           var method : ((String) -> ())? = nil
        viewController.method = {[weak self] valueFromC in
            self?.dataFromC = valueFromC
        }
    }
}
  

Если вы хотите передать значение родительскому контроллеру из BViewController , используйте self.method("yourValueFromB") , где вы измените значение. Для случая с CViewController используйте тот же подход.

Комментарии:

1. Итак, это было бы похоже на второй подход, который я опубликовал?

2. ДА. Существует так много способов сделать это. В приведенном выше примере используется внедрение зависимостей, и здесь передается функция ( closure ) от родительского контроллера method . Также вы можете перенести это в протоколы или объекты обработчика. Все комбинации работают.

Ответ №2:

Как правило, B должен отправлять данные обратно на исходный контроллер представления A с помощью шаблона протокола делегирования. Затем A должен иметь возможность решить в реализации метода делегирования, какие данные получены от B и куда отправлять эти данные, которые в данном случае являются C.

Таким образом, ваш код выглядит более организованным.