Как общаться между разными частями при использовании MVVM в iOS

Я провел свое исследование, но из-за того, что у меня недостаточно опыта, я не знаю, как лучше всего реализовать связь класса UserManger при использовании шаблона проектирования MVVM.

Итак, мое приложение-таймер синхронизировалось с облаком. Пока у меня HomeViewController, TimerViewModel, TimerModel, UserManager.

Объект UserManager заботится об аутентификации User, а также о передаче состояния аутентификации другим классам.

Штаты: .notSigned, .signing и .signed

Здесь мне нужно больше пояснений. Какому объекту UserManager должен сообщать обновленное состояние аутентификации? Он принадлежит контроллеру представления или модели представления?

И еще вопрос. Я не знаю, предполагается ли UserManager общаться только с одним классом или можно разговаривать со многими объектами одновременно. Я думаю, что большинству объектов одновременно нужно знать, подписан пользователь или нет. Если это правда, то какой вид коммуникации я реализую?

Для одного ко многим я думаю реализовать протокол Observable, описанный в этом статья. При необходимости могу скопировать код вместо ссылки на статью.

Надеюсь, я описал это хорошо. Буду признателен за любой ответ. Или любые новые идеи, общие идеи о том, как настроить связь объектов через приложение. Вы знаете какую-нибудь хорошую статью об этом?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 177
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вся бизнес-логика должна быть внутри ViewModel. ViewModel должна вызывать любой метод внутри UserManager. UserManager должен возвращать результат, проанализированный как модель, в модель представления. Затем ViewModel необходимо отформатировать данные и предупредить ViewController о завершении события/данных/сети и т. д.


Примеры форматирования данных:

  • Допустим, сетевой запрос дает вам firstName и lastName. Но у вас есть только 1 ярлык для отображения всего. ViewModel должна сложить эти строки вместе (с пробелом) и предоставить свойство fullName для VC.
  • Если вы вернули Double, но вам нужно отформатировать его в валюту и отобразить символ.
  • Получение метки времени и форматирование строки даты.

Это то, что должна делать ViewModel. Чтобы их можно было тестировать независимо от кода пользовательского интерфейса и жизненного цикла.


Коммуникация:

Вы можете использовать стандартные конструкции Apple API и создать протокол ViewModel с делегатом и обратным вызовом. Каждая виртуальная машина будет подтверждать протокол, VC установит себя в качестве делегата своей виртуальной машины и запустит ваш код внутри функции обратного вызова делегата VC.


Именование:

Слово «менеджер» потеряло популярность, потому что это обычно слово по умолчанию, используемое, когда использование класса неясно. По этой причине у него есть тысяча различных определений. Класс, отвечающий за выполнение сетевых запросов и/или сохранение состояния, должен называться "Сервис". то есть «Пользовательская служба».


Состояние обмена:

Я, наверное, многих разозлю этим. Но когда состояние необходимо разделить между несколькими VC, компонентами, виртуальными машинами и т. д., я следую шаблонам/архитектуре проектирования, которые настроены в Angular. Я делаю свои классы обслуживания синглтонами. Пусть они сохранят состояние. Тогда каждая ViewModel имеет один источник правды для каждого элемента и может форматировать его по своему желанию.

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


Обновлено: один ко многим:

Это может зависеть от вашего варианта использования и архитектурных решений. Я нашел возможным избежать проблемы «один ко многим» в большинстве моих случаев использования, если синглтон хранит состояние, а VC запускает что-то в ViewModel при каждом вызове viewDidAppear. Каждый раз, когда VC открывался, он получал последние данные и продолжал. Причина, по которой я избегаю «один ко многим», заключается в том, что в большинстве случаев на экране присутствует только 1 VC и выполняется код в любой момент времени (исключением является использование childViewControllers). Я обнаружил, что можно просто полностью обойти эту проблему и сохранить приложения простыми, изменив способ взаимодействия с данными, а не изменяя структуру API Apple.

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

NotificationCenter — не мой любимый подход, но если бы я столкнулся с ситуацией «один ко многим», которую я не мог бы избежать, я бы попробовал его. Как упоминалось в статье, у быстрых функций есть некоторые недостатки, к которым вы можете получить доступ с помощью этого средства. По крайней мере, у него есть дополнительное преимущество: оно существует уже давно, хорошо изучено и вряд ли сильно изменится. Не будет большой кривой обучения, если другие разработчики будут работать над этим приложением.

Интересен другой подход, упомянутый в статье, — создание собственной урезанной версии RxSwift для добавления в проект наблюдателей. Моя проблема с RxSwift в данный момент заключается в том, что люди не используют его в сочетании с синглтонами или какой-либо центральной точкой управления. Когда у вас есть Observable на объекте A, Observable by B, у которого также есть другой Observable, Observable by C, который вызывает функцию на D, которую наблюдают E, F и G.... и так далее. Этот стиль кода невероятно запутан, трудно читаем, подвержен ошибкам и труден для отладки. До тех пор, пока этого избегают, и это синглтон, который имеет наблюдаемое, и все ViewModels наблюдают, я думаю, что что-то подобное было бы в порядке, если вы готовы приложить усилия для его создания и обслуживания.

Отличное объяснение, и я нахожу его очень полезным. Только для последнего абзаца я хотел бы узнать больше о том, как singleton уведомляет другие модели представления. Похоже, это один ко многим? Насколько я знаю, по умолчанию делегаты только один к одному. Вы пользуетесь центром уведомлений или как?

Klemen 29.05.2019 14:21

@KlemenZagar Я отредактировал вопрос, так как мой ответ был слишком длинным

Simon McLoughlin 29.05.2019 15:09

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