Я провел свое исследование, но из-за того, что у меня недостаточно опыта, я не знаю, как лучше всего реализовать связь класса UserManger
при использовании шаблона проектирования MVVM.
Итак, мое приложение-таймер синхронизировалось с облаком.
Пока у меня HomeViewController
, TimerViewModel
, TimerModel
, UserManager
.
Объект UserManager
заботится об аутентификации User
, а также о передаче состояния аутентификации другим классам.
Штаты:
.notSigned
, .signing
и .signed
Здесь мне нужно больше пояснений. Какому объекту UserManager
должен сообщать обновленное состояние аутентификации? Он принадлежит контроллеру представления или модели представления?
И еще вопрос. Я не знаю, предполагается ли UserManager
общаться только с одним классом или можно разговаривать со многими объектами одновременно.
Я думаю, что большинству объектов одновременно нужно знать, подписан пользователь или нет. Если это правда, то какой вид коммуникации я реализую?
Для одного ко многим я думаю реализовать протокол Observable, описанный в этом статья. При необходимости могу скопировать код вместо ссылки на статью.
Надеюсь, я описал это хорошо. Буду признателен за любой ответ. Или любые новые идеи, общие идеи о том, как настроить связь объектов через приложение. Вы знаете какую-нибудь хорошую статью об этом?
Вся бизнес-логика должна быть внутри ViewModel. ViewModel должна вызывать любой метод внутри UserManager. UserManager должен возвращать результат, проанализированный как модель, в модель представления. Затем ViewModel необходимо отформатировать данные и предупредить ViewController о завершении события/данных/сети и т. д.
Примеры форматирования данных:
firstName
и lastName
. Но у вас есть только 1 ярлык для отображения всего. ViewModel должна сложить эти строки вместе (с пробелом) и предоставить свойство fullName
для VC.Это то, что должна делать 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 наблюдают, я думаю, что что-то подобное было бы в порядке, если вы готовы приложить усилия для его создания и обслуживания.
@KlemenZagar Я отредактировал вопрос, так как мой ответ был слишком длинным
Отличное объяснение, и я нахожу его очень полезным. Только для последнего абзаца я хотел бы узнать больше о том, как singleton уведомляет другие модели представления. Похоже, это один ко многим? Насколько я знаю, по умолчанию делегаты только один к одному. Вы пользуетесь центром уведомлений или как?