Понимание методов TextFieldDelegate с помощью собственного SwiftUI

Вот и осталось меньше недели до производственного выпуска iOS 15, и я все еще слышу, что SwiftUI не готов к производству. К сожалению, это становится городским мифом.

Это правда или истеблишмент недостаточно старается? Если честно, в этом есть доля правды. TextView и ScrollView являются хорошими примерами элементов пользовательского интерфейса в UIKit, которые в основном отсутствуют в SwiftUI или в последнем, который был реализован лишь частично. Но это очень подвижная цель, и, приложив немного усилий, можно добиться замечательно хороших результатов.

И, учитывая, что возможности SwiftUI по разметке на световые годы опережают UIKit, я думаю, что оно того стоит.

Давайте посмотрим на другой пример, TextField. Это реализовано в SwiftUI, но, как и ScrollView, на первый взгляд не выглядит полной реализацией. Присоединяйтесь ко мне в путешествии, чтобы разобраться в этом с немного большей энергией. Я хочу попробовать реализовать TextField со всеми обрезками, не прибегая к UIViewRepresentable. Хочу родное решение.

Краткое

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

Теперь я хочу реализовать как можно больше из них, не прибегая к UIViewRepresentable.

Мы должны начать с реализации расширения, чтобы сообщать, присутствует ли клавиатура на экране.

Если он присутствует, то очевидно, что кто-то нажал на ваш TextField. Конечно, если у нас более одного TextField, мы можем не знать, какое из них используется в SwiftUI. Это упущение, которое Apple решила в iOS 15, и вам будет приятно узнать, но я не собираюсь здесь рассказывать об этом. Хотя я думаю, что могу немного обойти это, читайте дальше. Начнем с кода для обнаружения клавиатуры.

И что ж - раз уж вы это делаете, вот код, чтобы убрать клавиатуру - он вам тоже понадобится.

func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}

Конечно, у нас есть SwiftUI с тегами onCommit и onEditingChanged. Эти два тега между ними охватывают состояния textFieldDidDidBeginEditing и textFieldDidDidEndEditing.

Чтобы управлять редактированием самого текста, вы можете использовать тег onChange, который может сообщать об изменениях в TextField и реагировать соответствующим образом.

В примере кода, который я показываю здесь, мы ограничиваем ввод только прописными буквами:

Краткий обзор того, что делает остальная часть кода:

  • Мы использовали класс для хранения переменной, указанной в поле ввода текста, чтобы я мог легко получить к нему доступ за пределами кода SwiftUI.
  • Там использовались шаблоны willSet и didSet, к которым я мог бы добавить еще PassThroughSubjects.
  • Два магических числа 123 и 789 - не более чем ссылки на поля, поэтому я могу сказать, какое из них в настоящее время активно.
  • Оба поля включены по мере их появления, очевидно, вы можете закодировать их по-другому, если это имеет смысл.
  • Используя шаблон SwiftUI, введите текстовый флаг isEditing в сочетании с currentFieldPublisher ID, чтобы указать, какое сообщение (начать редактирование или завершить редактирование) отправить.
  • Отображает клавиатуру при нажатии на поле и закрывает ее при нажатии клавиши возврата.
  • Добавлено несколько PassThroughSubjects для ответа на комбинированные сообщения begin / end + clear + enable / disable.

Анимированный GIF здесь показывает различные сообщения и ссылку на поле. Последний появляется, когда вы нажимаете в поле в виде числа. Начало редактирования отображается зеленым кружком, окончание редактирования - красным кружком… оранжевым - ни то, ни другое. Также очевидно, что вы ничего не видите, когда я не ввожу заглавную букву в первое слово, летучая мышь.

Заключение

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