Аутентификация телефонного номера с реактивным программированием

1656660143 autentifikacziya telefonnogo nomera s reaktivnym programmirovaniem

от Jinwoo Choi

1*PyLjEXgdDViFQJarHsi7lw

Аутентификация телефонного номера

Многие мобильные приложения требуют членства. Большинство из них обеспечивают аутентификацию пользователя. Это связано с тем, что вам нужно проверить, является ли пользователь используемым тем же, что и подписчик, когда предотвращаете дублирование подписок или изменяете пароли.

Большинство мобильных приложений используют номер телефона для проверки подлинности пользователей, поскольку они работают на мобильных телефонах. Аутентификация номера телефона состоит из нескольких этапов, т.е. Вы также должны изменить пользовательский интерфейс. Это также требует асинхронной обработки событий, таких как запрос кода подтверждения и передача введенного пользователем кода на сервер.

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

Поток пользовательского интерфейса для аутентификации номера телефона

1*YOEtnAFE5I6BatRw0swIqA

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

  • активировать [Request verification code] Кнопка при вводе телефонного номера (шаг 1)
  • Скрыть [Verification code] TextField и [Authenticate] Кнопка, когда аутентификация прошла успешно (Шаг 4)
  • Отображать соответствующее сообщение (подсказку), когда аутентификация завершена или не удалось (шаг 5)

Основная структура

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

enum PhoneNumberVerifyStep {    case inputPhoneNumber, inputVerifyNumber, verifying, succeed, failed}

Компоненты пользовательского интерфейса состоят из двух текстовых полей, двух кнопок и одной метки. Все они созданы с помощью InterfaceBuilder и подключены к IBOutlet. Как упоминалось ранее, мы объявили свойство класса для хранения шага проверки подлинности под названием verifyStep, и мы добавили наблюдателя didSet для обработки изменений интерфейса пользователя.

Изменить пользовательский интерфейс на основе этапа аутентификации

Вот та часть, которая фактически изменяет пользовательский интерфейс. Установите свойство isHidden для [Verification code] TextField и [Authentication] Кнопка в соответствии с измененным значением verifyStepа также изменить текст [Tip] Метка.

После вызова Restful API с [Authentication] Метод действия кнопки установите соответствующее значение verifyStep в соответствии с ответом. Поскольку мы использовали наблюдатель didSet для изменения пользовательского интерфейса, есть преимущество разделить код интерфейса и код обработки данных.

Есть ли [Request verification code] Активность кнопки зависит от входного значения в реальном времени [Phone number] TextField, а не шаг аутентификации. Поэтому мы добавляем обработчик действия phoneNumberTextField что устанавливает isEnabled с requestVerifyNumberButton в соответствии с входным значением.

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

Сначала, внутренняя реализация наблюдателя didSet в verifyStep может быть слишком велика. И код, устанавливающий одно представление, может существовать в нескольких случаях в операторе Switch. Многие части необходимо изменить, чтобы удалить конкретное представление или добавить новое представление. Прежде всего, его трудно читать, если код становится длиннее.

Изменение свойства enable Button в соответствии с входным значением TextField может быть неудобным: обработчик события ввода текста следует постоянно добавлять, если количество текстовых полей и кнопок, требующих подобной обработки, увеличивается. Если вам нужно добавить логику проверки в реальном времени к входному значению в TextField, внутренняя часть обработчика событий может быть сложной.

Теперь давайте устраним эти недостатки, применив реактивное программирование. Здесь мы используем библиотеку с открытым кодом ReactiveCocoa.

Реактивное программирование

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

Реактивное программирование – это программирование с асинхронными потоками данных.

В определенном смысле это не что-то новое. Шины событий или типичные события щелчка на самом деле являются асинхронным потоком событий, на котором вы можете наблюдать и делать некоторые побочные эффекты. Reactive – это идея о стероидах. Вы можете создавать потоки данных чего угодно, не только из событий щелчка и наведения курсора

Однако реактивное программирование выходит за рамки простого использования вышеупомянутых инструментов и использует шаблон наблюдателя как основу программирования.

Он абстрагирует поток всех типов примитивных данных, обрабатываемых пользовательским интерфейсом — Control Action, Notification, Delegate и KVO, которые являются основными инструментами, предоставленными Cocoa, как поток. Он также предоставляет функции для обработки и фильтрации проходящих через него данных, которые можно легко использовать в различных сферах.

Другими словами, реактивное программирование – это a более интегрированный и простой способ обработки обработки цепной реакции (и программирование на ее основе) из-за изменений состояния чем традиционные методы

По сути, его функционально-ориентированная кодировка направлена ​​на выполнение одной роли в функции, подключенной к потоку. Это позволяет избежать сложных программ по сохранению состояния, таких как наблюдатель verifyStep didSet из предыдущего примера, и облегчает обработку ошибок и управление параллельным выполнением асинхронной обработки. Для получения дополнительной информации см. ReactiveX.io.

Внедрить реактивное программирование

Ладно, пора прекратить объяснять длинные скучные теории. Теперь давайте улучшим пример аутентификации номера телефона с помощью библиотеки с открытым кодом ReactiveCocoa.

Прежде всего, мы удаляем код, изменяющий пользовательский интерфейс в соответствии с шагом аутентификации в предыдущем примере, и остается лишь базовый скелет ViewController. Мы также удаляем наблюдатель didSet для verifyStep, обработчик действия редактирования для TextField и метод действия для [Authenticate] Кнопка.

Реализуйте следующий код с помощью ReactiveCocoa на основе скелета. Весь код был добавлен, поскольку он был недолгим. Давайте сначала посмотрим Собственность ReactiveSwift, и рассмотрим реализацию, разделив процесс этапа аутентификации на три типа, как показано в предыдущем примере.

(Сменное) свойство ReactiveSwift

Property – это класс, предоставленный ReactiveSwift, являющийся основой ReactiveCocoa. Он дает возможность обрабатывать данные как поток. Например, в примере кода verifyStep является владельцем данных типа PhoneNumberVerifyStep. Он может генерировать сигнал при изменении значения или изменять значение в ответ на другие изменения данных.

var verifyStep = MutableProperty<PhoneNumberVerifyStep(...)

То есть, когда меняется значение Property (verifyStep), интерфейс пользователя можно изменить. Или, когда входное значение TextField изменено, значение переменной (verifyStep) можно изменить вместе с ним. Наблюдатель didSet свойства класса Swift обеспечивает аналогичную функциональность. Однако MutableProperty имеет преимущество в том, что он может изменить или отфильтровать значения, проходящие через поток как описано выше, и к свяжитесь с кодом изменения пользовательского интерфейса гораздо сжато.

Привязка пользовательского интерфейса и оператор <~ ReactiveCocoa

ReactiveCocoa обеспечивает Binding для легкой обработки изменений пользовательского интерфейса через изменения свойств. Компонент пользовательского интерфейса может создать BindingTarget для каждого из своих конфигурированных атрибутов. И это имеет форму командного шаблона.

Например, ReactiveCocoa предоставляет BindingTarget, которая является командой, изменяющей текст UILabel. BindingTarget производится, когда сигнал генерируется из потока и устанавливает полученное значение для текста UILabel.

Оператор <~ предоставляется, чтобы облегчить подключение сигнала к BindingTarget. Например, приведенный ниже код устанавливает значение (входящее значение), переданное из Сигнала (генерируемого при изменении значения textField) в текст метки.

label.reactive.text <~ textField.reactive.continuousTextValues

label.reactive.text возвращает a BindingTarget экземпляр, изменяющий текст, и textField.reactive.continuousTextValues возвращает a Сигнал экземпляр, вызывающий событие, когда меняется входное значение. The BindingTarget экземпляр и Сигнал экземпляр связан &lt;~, поэтому когда входное значение textField изменяется, текст метки изменяется вместе с ним.

Привязка интерфейса ReactiveCocoa является важной концепцией, которая играет ключевую роль в реализации дизайна MVVM. Это объясняется тем, что можно отделить код обработки данных от кода обработки пользовательского интерфейса путем связывания свойств ViewModel с компонентами интерфейса пользователя в представлении.

Реактивная цепная реакция

Теперь вернитесь к примеру кода и посмотрите, как используются свойства и привязка пользовательского интерфейса. Начнем с процесса активации [Request verification code] Кнопка при вводе номера телефона. BindingTarget кнопки подписывается на сигнал изменения входящего значения, созданный непрерывными текстовыми значениями TextField, описанными выше.

requestVerifyNumberButton.reactive.isEnabled &lt;~     phoneNumberTextField.reactive.continuousTextValues    .map { !($0?.isEmpty ?? true) }

IsEnabled BindingTarget для requestVerifyNumberButton было привязано к сигналу изменения входящего значения для phoneNumberTextField, и в процессе использовался оператор <~.

Свойство isEnabled кнопки является свойством типа Bool. Входящее значение TextField является типом строки, поэтому значение нельзя назначить напрямую.

Таким образом, когда передается значение строки, оно изменяется на тип Bool с помощью метода карты Signal. Понятно, что потоковые данные, что является ключевым преимуществом реактивного программированиялегко прорабатывать, и его можно выразить кратко и лаконично.

Давайте посмотрим на изменение состояния Button, TextField и Label в зависимости от значения verifyStep, занимающего большую часть примера.

var verifyStep = MutableProperty<PhoneNumberVerifyStep>(...)

Во-первых, verifyStep объявляется как MutableProperty. verifyStep теперь может служить потоком данных, а компоненты пользовательского интерфейса могут подписываться на сигнал изменения значения из него. Свойство value возвращает примитивное значение verifyStep.

Ниже приведены привязки компонентов пользовательского интерфейса к сигналу verifyStep. Подобным образом оператор <~ соединяет BindingTarget, изменяющий свойства isHidden и text компонентов пользовательского интерфейса, с сигналом от verifyStep. То есть, если меняется значение verifyStep, атрибуты пользовательского интерфейса, такие как isHidden и текст, изменяются соответственно.

verifyNumberTextField.reactive.isHidden <~ verifyStep    .map { $0 == .succeed }
verifyButton.reactive.isHidden <~ verifyStep.map { $0 == .succeed }
statusLabel.reactive.isHidden <~ verifyStep.map { !$0.isVerifiedStep }
statusLabel.reactive.text <~ verifyStep.signal    .filter { $0.isVerifiedStep }.map { $0 == .succeed ? ... }

Использовать карта способ связывания значения типа Enum под заглавием PhoneNumberVerifyStep со свойством типа Bool. Использовать фильтр чтобы убедиться, что текст в statusLabel изменяется, только если verifyStep имеет значение .succeed или .failed.

До этого момента цепная реакция между данными и интерфейсом пользователя была усовершенствована реактивным способом при внедрении аутентификации телефонного номера. Больше наблюдателей didSet не требуется. Также пропали сложные методы изменения интерфейса.

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

Наконец, давайте рассмотрим, как обрабатывать событие управления пользовательским интерфейсом через ReactiveCocoa.

Обработка событий для управления интерфейсом пользователя с помощью ReactiveCocoa

ReactiveCocoa также предоставляет способ обработки событий для управления интерфейсом пользователя в качестве потоков. Подобно continuousTextValues ​​TextField, которые мы видели ранее, ReactiveCocoa добавила свойство, которое возвращает экземпляр Signal для события управления компонента пользовательского интерфейса. Сигнал для события пользовательского интерфейса может быть привязан к BindingTarget или непосредственно иметь наблюдателя.

verifyButton.reactive.controlEvents(.touchUpInside).observeValues {     self.api.getUsersVerify(...)        .on(value: { _ in            self.verifyStep.value = .succeed        })        .on(failed: { error in            self.verifyStep.value = .failed        })}

В этом примере мы добавили наблюдатель к сигналу события интерфейса пользователя. Метод controlEvents вернул сигнал для события touchUpInside, а обработчик наблюдателя был добавлен через метод observValues.

Простой процесс изменения текста метки при нажатии кнопки возможен путем привязки через оператор <~.

label.reactive.text <~ button.reactive.controlEvents(.touchUpInside)    .map { _ in "hello" }

Давайте напомним текущий процесс. Если во время подписки на поток события пользовательского интерфейса возникает сигнал, он вызывает Remote API. Измените значение MutableProperty в соответствии со значением, переданным обработчику ответа асинхронного вызова. В то же время сигнал изменения значения генерируется из потока MutableProperty, и UI, привязанный к сигналу изменения, изменяется.

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

Вывод

Мы изменили традиционную аутентификацию телефона на использование реактивного программирования. Это не новая концепция – Swift и Cocoa уже предоставляют много инструментов для асинхронной обработки, обработки событий пользовательского интерфейса и внедрения шаблона наблюдения. Однако использование реактивного способа является более элегантным и лаконичным, чем классический способ. Кроме того, есть преимущество в том, что его можно использовать для разработки структуры приложения, как MVVM.

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

Давайте еще раз посмотрим преимущества реактивного программирования:

  • Код, реагирующий на изменения в конкретных данных или компонентах пользовательского интерфейса, упрощен.
  • Поскольку вам не нужно создавать огромный метод целенаправленного кода, изменяющего пользовательский интерфейс, становится легче иметь дело с новыми состояниями или добавлять или удалять компоненты пользовательского интерфейса.
  • Функциональная кодировка позволяет писать код, который может сосредоточиться на ситуациях и ролях.
  • С помощью Observing and Binding можно разделить ViewController на ViewModel и View, что является ключевым фактором в применении дизайна MVVM.

Я надеюсь, что многие разработчики смогут счастливее кодировать благодаря реактивному программированию. Спасибо, что прочли эту историю.

Я пишу о разработке приложений для iOS с помощью Swift. Я также буду признателен за ваш интерес к следующим статьям.

Синтаксис Promise из ReactiveSwift
Используйте ReactiveSwift для написания кода, подобного Promise, в JavaScript.medium.comИспользование Enum в Swift
Как обрабатывать константы, необработанные значения и выражения типа Enum через Swiftmedium.comПередача параметров в Restful API с помощью Swift Codable
Как можно легко обрабатывать не только данные, полученные от Restful API, но и данные, которые нужно передать через…medium.com

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *