Reeeewind

Redux - это система управления состоянием. Заинтригованы? Читать дальше

Сложность: Начинающий | Легко | Нормальный | Испытывающий

Эта статья была разработана с использованием Xcode 11.4.1 и Swift 5.2.2.

Эта статья была обновлена ​​для Xcode 12.4 и Swift 5.3.2.

Предпосылки:

  • Кодирование в Swift Playgrounds (гайд ЗДЕСЬ)

Терминология:

Redux: библиотека JavaScript с открытым исходным кодом для управления состоянием приложения

Использование Redux в проектах

Преимущества:

  • Функции чистого редуктора упрощают тестирование бизнес-логики
  • Централизация состояния упрощает отладку
  • Приветствуется нормализация данных. Конечным результатом является то, что у вас не будет нескольких независимых копий одних и тех же данных, которые не знают друг друга и не могут быть легко обновлены.
  • Состояние может быть сохранено в локальном хранилище, которое затем можно использовать для загрузки или возврата приложения в это состояние.
  • Поскольку redux строго относится к организации кода, у нас есть преимущества, которые дает обслуживание кода.
  • Легко отлаживать

Недостатки:

  • Само состояние неизменяемо и может быть обновлено только редуктором. Это само по себе может увеличить требования к памяти системы.
  • Ограниченный дизайн со стандартным кодом
  • Жесткость и сложность, которые делают redux подходящим для очень больших проектов, означает, что он часто не подходит для многих небольших проектов.
  • Действия не связаны с их эффектами (которые хранятся в редукторе)

Вам вообще нужен Redux?

Одним из основных недостатков Redux является то, что он может вам не понадобиться в вашем проекте (по крайней мере, пока). Так как же узнать, действительно ли вашему приложению требуется Redux?

  • У вас есть большое состояние приложения, которое требуется во многих частях вашего приложения
  • Состояние вашего приложения часто обновляется
  • Состояние вашего приложения сложно обновить
  • Ваше приложение имеет кодовую базу среднего и большого размера, над которой работают многие люди.
  • Вам нужно видеть, как состояние обновляется с течением времени

Компоненты Redux

Состояние: состояние приложения, которое считается источником истины. Хотя может быть только одно состояние, его можно разделить на подсостояния.

Действия: объекты, описывающие, что может делать система. Отправляется представлением как намерение изменить состояние приложения.

Редукторы: основная логика приложения и создание нового состояния для приложения с учетом действия и текущего состояния. Они должны быть чистыми функциями без побочных эффектов и синхронными (это затронуто в заключении, но именно поэтому этот пример проекта не содержит никаких сетевых функций).

Связь с МВИ

Здесь есть связь с Android, а точнее с MVI.

Итак, Redux на самом деле является MVI, потому что редуктор - это модель, действия - это намерение, а состояние - это… redux

Управление компонентами пользовательского интерфейса

Обновление компонента пользовательского интерфейса может быть выполнено с помощью хранилища Redux, возможно, с сохранением текста внутри метки.

Redux:

  • Вызов действия
  • Передать данные редуктору
  • Обновите магазин

Императив:

  • Поддерживать локальную переменную состояния

Решение состоит в том, что оставить в запасе, а что выбрать в состоянии (и даже думать об этом как о битве между декларативным и императивным программированием). Соблазн держать все в состоянии велик, но для (тривиальных?) Элементов пользовательского интерфейса нет смысла перегружать состояние каждым компонентом.

Пример проекта

Создание проекта

Мы создаем проект единого представления, а затем используем Swift Package Manager, чтобы включить зависимость от https://github.com/ReSwift/ReSwift (до следующего основного).

Функциональные возможности приложения

Это конкретное приложение будет иметь множество людей

let people: [Person] = [Person(name: “James”), Person(name: “Ahmed”)]

и будет отображать имя человека по одному, начиная с первого человека. При нажатии кнопки next отображается следующий человек в списке.

Да это некрасиво.

Да, это просто UILabel на контроллере представления с UIButton внизу. Здесь нет ничего интересного - это статья об архитектуре, так что, пожалуйста, потерпите меня.

Код

Обратите внимание, что большинству (если не всем) из этих классов потребуется import ReSwift - так что с учетом сказанного давайте намочим ноги!

Есть основной магазин, который я поместил в Constants.swift файл. Здесь также можно объявить middleware.

AppState - это то место, где находится основная часть этого проекта - здесь у нас есть array человека и currentIndex, который действует как указатель на соответствующего человека в списке.

Это подключается к Person struct просто содержит имя каждого Person

Редуктор - это бизнес-логика приложения, а также инициализирует исходное состояние, если оно не указано при вызове reducer.

Действие довольно тривиально struct, как показано в следующем фрагменте кода.

это связано с помощью следующего ViewController. Обратите внимание, как он соответствует StoreSubscriber protocol, что означает, что мы должны добавить typealias, как показано во фрагменте кода. Действие кнопки создает dispatch действие, которое поражает редуктор - фантастика! Когда редуктор выполняет свою работу, он попадает в функцию newState и, как показано в приведенном ниже коде, но, к сожалению, возвращает все состояние (а не его фрагмент).

О, и мы, должно быть, убедились, что подписались на mainStore в viewDidLoad() здесь через mainStore вызов mainStore.subscribe(self), который связывает контроллер представления с mainStore.

Вывод

Следующим этапом этого будет добавление промежуточного программного обеспечения, которое обеспечивает точку расширения между отправкой действия и достижением этого действия редуктора, который затем заставит нас задуматься о redux-thunk. Проще говоря, редукторы здесь должны быть чистыми функциями (без побочных эффектов), что означает, что вызовы API не могут выполняться внутри редуктора - это становится немного сложнее и, следовательно, потребуется сама статья!

Оглядываясь назад на эту статью, мы видим, что ReSwift (пока) не выполняет различие в состоянии - поэтому просто возвращает newState при изменении состояния, что означает, что (в этой конкретной реализации) это должно быть обработано в представлении, что-то, что явно было бы не лучшим.

Могу ли я использовать ReSwift в рабочем приложении? Что ж, SwiftUI может быть наиболее продуктивным способом управления состоянием и достижения прогресса в этой области, а не поиск решений в Интернете или Android.

Ой. Хотите репо с примером проекта. Считайте это сделанным ».

Если у вас есть вопросы, комментарии или предложения, пишите мне в Twitter.

Не стесняйтесь подписаться на мою рассылку новостей