Сбор данных из нескольких ViewControllers в Swift - PullRequest
0 голосов
/ 12 мая 2018

У меня есть несколько контроллеров представления (в стеке навигации или, возможно, нет), и каждый контроллер собирает некоторые данные на основе ввода пользователя.В конце мне нужно использовать эти данные в последнем контроллере.

Итак, какой будет наилучший подход / шаблон проектирования для реализации этого сценария?

Ответы [ 4 ]

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

На мой взгляд, лучший способ справиться с этим - использовать шаблон проектирования Flux . На github есть инфраструктура ReSwift , которая обеспечивает однонаправленный поток данных, аналогичный Redux .

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

Еще одним преимуществом является то, что если вам нужно разбить ваши контроллеры представлений на несколько контроллеров представлений через контейнеры, т. Е. На одном экране имеется более 2 контроллеров представлений, вам не нужно будет создавать больше инфраструктуры для передачи данных между теми, которые по моему опыту получают действительно грязный.

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

Ну, на мой взгляд, лучший подход - это использовать шаблон архитектуры MVVM (Model-View-ViewModel).

1) Для каждого из ваших UIViewController создайте отдельный класс (производный от NSObject, если хотите), который вы считаете «моделью представления», принадлежащей этому UIViewController. Вашим контроллерам представления не разрешен доступ к классам модели ... теперь это работа ваших классов "модели представления".

2) Создайте синглтон с именем, скажем, DependencyManager. Ваши модели представлений обращаются к нему, чтобы получить ваши модели (или, по крайней мере, модели верхнего уровня, если они иерархические) и все, что им может понадобиться, например, сетевые сервисы и т. Д. DependencyManager действует как способ, которым ваши модульные тесты могут внедрить замену ». "Моделирование" версий ваших моделей, сетевых служб и т. д. ... когда пришло время протестировать каждую модель представления.

3) Создайте класс (ы) вашей модели, которые содержат данные. Ваши контроллеры представления собрали различные данные в элементах управления пользовательского интерфейса и передали эти необработанные данные вашим viewModels. Модели представления могут изменять эти данные (или нет) и прикреплять их к соответствующим моделям, которые они получают из DependencyManager.

4) ViewController также может запрашивать данные у своего viewModel. Таким образом, ваш последний ViewController будет получать все необходимые данные из своей viewModel.

Помните: ViewControllers не должны напрямую манипулировать вашими модельными классами. Кроме того, ваши ViewModels никогда не должны ссылаться на какие-либо объекты пользовательского интерфейса или даже иметь ссылку на свой ViewController.

Примечание: я рекомендую, чтобы каждая ViewModel соответствовала протоколу, который происходит от пустого протокола с именем что-то вроде «MockableViewModelProtocol». Вы можете добавить одно свойство к вашему DependencyManager типа MockableViewModelProtocol, которое каждый из ваших ViewControllers может проверить перед созданием своей ViewModel, в случае, если модульный тест назначил фиктивную ViewModel для замены ViewController. Еще одним преимуществом такого протокола является быстрое и четкое понимание взаимосвязи между ViewModel и его ViewController. Часто у вас будут не только свойства и методы, но и свойства обратного вызова (свойства замыкания).

Итак, поехали. Это, на мой взгляд, лучший способ не только разработать способ управления и доступа к данным среди множества viewControllers, но также протестировать все ваши классы и их использование этих данных.

И в отличие от всех текущих утверждений, что раскадровки блокируют внедрение зависимостей и, таким образом, предотвращают тестирование ваших контроллеров ViewController, это всего лишь пустяк. Используя DependencyManager, так что тесты вашего контроллера представления внедряют там макеты, тесты получают то же преимущество, как если бы они вводили макет непосредственно в ViewController, и, тем не менее, ViewController все еще создается Storyboard. С таким подходом я успешно отправил большое приложение.

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

Если у вас есть (стек навигации) и вам нужно собрать данные со всех этих контроллеров представления

лучший способ не использовать пользовательские настройки по умолчанию, или Singleton

для вашего случая выдолжен сделать контейнер контроллеров представления для обработки конкретного процесса.Примечание (UINavigationController, UITabBarController и UISplitViewController * - это просто контейнеры)

Например, создайте учетную запись , которая требует 4 шага для сбора входных данных пользователей,каждый шаг представлен ViewController, и в конце вам нужно отправить все эти данные на сервер API,

. Поэтому создайте Parent ContainerViewController дочерних viewControllers и используйте Delegation для передачи данных после каждого шага в ParentViewController, ParentViewControllerбудет лидером, чтобы разрешить следующий шаг и предоставить данные для этого шага.Вот как начать создавать свой собственный Контейнер , управляющий view-controllers-with-container

Не используйте Singleton

Синглеты могут бытьдоступ прямо из любого места в приложении.У вас нет контроля.Соединение a-lot в вашем коде и затруднение тестирования ваших объектов в будущем

Не используйте UserDefaults

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

Поэтому вам придется использовать шаблон архитектуры в будущем

Архитектура

Каждый ViewController должен заботиться только о своем собственном экране.также viewController не должен знать друг о друге.если мы сделаем это, мы удалим много связей между нашими классами контроллера представления.

Так что вы можете использовать Координатор , чтобы быть Лидером, который обрабатывает всю навигацию Координатор

и проверьте, как интегрировать с MVVM на MVVM-C

также Viper использует эту технику для обработки навигации навигации Viper

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

Для этого может быть несколько способов:

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

  2. Используйте Singleton для хранения данных с каждого контроллера.Единственная проблема с Singleton заключается в том, что он будет сохраняться в вашем приложении.

  3. Вы также можете сохранить данные в UserDefaults.После использования данных вы можете удалить их из UserDefaults.

Дайте мне знать, если у вас все еще есть какие-либо проблемы.

...