Простота SwiftUI

Я буду честен. Я не хотел любить SwiftUI… но я люблю. С момента запуска SwiftUI в конце 2019 года я был непреклонен в том, что не собираюсь его использовать, и буду придерживаться исключительно UIKit.

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

Swift как язык дал команде Apple время подумать о том, что часто делают разработчики iOS, и о проблемах, с которыми столкнулся UIKit.

Вы хотите сделать что-то простое, например добавить отступ к метке или изображение внутри пользовательской кнопки с текстом? Конечно…!

Вы можете создать подкласс UILabel и initialize с помощью какого-либо UIEdgeInsets или добавить функции или свойства переопределения для своего подкласса, такие как intrinsicContentSize: CGSize.

Есть много правильных решений, но SwiftUI производит сильное впечатление на ViewModifiers.



Поиграв немного со SwiftUI за последние несколько дней, я действительно увидел привлекательность этой новой разработки Swift.

Несколько недель назад я написал статью с решением моей небольшой проблемы «Изображение в UITextField» и решил попробовать ее в SwiftUI!

Я уверен, что многие из вас, читающих это, сочтут это тривиальным в SwiftUI.

Эта статья не предназначена для людей, которые в настоящее время изучают/знают SwiftUI. Вместо этого я хочу показать пример чего-то, что я ранее создал в UIKit, для тех, кто ищет несколько прямого сравнения.

Первый результат

Код ниже — это то, что используется для приведенного выше GIF. Это очень простой пример.

Я завернул его в NavigationView (UINavigationController только для пользователей UIKit) и добавил его в Form, который кажется эквивалентным UITableView.

Хотя это выглядит немного повторяющимся, верно? Я почти не могу поверить, что пишу это. Мы уже сэкономили на многих строках кода, настраивая наши UITableView, UINavigationController/UICollectionView, NSLayoutConstraint, UITableViewDelegate, UITableViewDataSource… не забывая о пользовательском UITextField сверху!

Небольшой рефакторинг

Если мы нажмем клавишу cmd и щелкнем HStack, мы сможем выделить этот раздел кода в отдельное подпредставление:

Затем Swift любезно назовет это ExtractedView() для нас, пока мы не найдем для него подходящее имя и не поместим его ниже ContentView().

Я собираюсь переименовать этот PersonalInfoStack и добавить 3 новых свойства для наших image и textField.

Это возвращает «какой-то View», в этом примере он вернет HStack с image и textField. Затем мы передаем свойства через новый конструктор, когда вызываем экземпляр PersonalInfoStack():

Поскольку мы используем свойство @State в нашем новом подпредставлении, нам нужно использовать ключевое слово @Binding здесь в нашем свойстве textFieldText: String, чтобы сообщить Swift: «Эй, я собираюсь использовать здесь значение, но я хочу, чтобы оно было то же, что и то, что я передаю… Если я обновлю здесь, обновите его там, где он изначально объявлен».

Теперь о новом рефакторинге ContentView:

Хорошо, добираемся.

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

Чего мы не хотим добиться, так это проблемы MVC, когда код становится нечитаемым/сложным в управлении!

Вы можете рефакторить Section, но будьте осторожны; есть тонкая грань между абстракцией ради здравого смысла и абстракцией, которая настолько абстрактна, что вы не можете понять, что происходит!

Лично мне нравится оставлять определенные части кода такими, какие они есть, чтобы улучшить читабельность, например, принять решение не рефакторить Section.

При написании кода я часто использую alt + cmd +< или alt + cmd + >, чтобы свернуть и открыть код. Это определенно долгожданный маленький помощник для более длинных ContentView():

Идем дальше!

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

В UIKit мы бы установили для свойства textField.isSecureTextEntry значение = true. В SwiftUI мы можем написать следующее:

Как вы можете видеть выше, мы добавили логическое значение, которое определяет, виден пароль или нет.

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

Это не дамп UIKit!

На самом деле я столкнулся с интересной заминкой при попытке изменить цвет фона Form в SwiftUI и довольно быстро обнаружил, что мне пришлось вернуться к UIKit. Я ожидал, что смогу добавить модификатор Color к Form.

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

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

Мое использование UIKit по-прежнему будет присутствовать, но только из этого небольшого примера и моего сравнения реализации одних и тех же вещей в UIKit и SwiftUI можно с уверенностью сказать, что SwiftUI будет чем-то, о чем я очень хочу узнать больше!

Спасибо за прочтение.