SwiftUI и Combine, последние фреймворки Apple, стали основными событиями WWDC этого года. Долгожданный декларативный пользовательский интерфейс, наконец, стал реальностью, и это действительно событие исторических масштабов в мире разработки iOS.
Его декларативный подход противоречит обязательному, который разработчики iOS, включая нас, использовали до iOS 13. Неудивительно, что они взволнованы! Это устраняет множество сложностей в процессе построения пользовательского интерфейса.
Представляя Combine, Apple сделала первые шаги в направлении функционально-реактивного программирования (FRP), которое, как ожидается, станет популярным в ближайшие годы. Apple делает успехи. Для конечных пользователей это означает, что разработчики быстрее выполнят их требования.
Но, возможно, наиболее полезный эффект можно получить, если заставить Combine работать вместе со SwiftUI для улучшения процесса разработки с помощью соответствующих руководств и, следовательно, для создания лучших приложений.
Вам также может понравиться:
Как запускать тесты Swift UI с помощью Mock API Server
SwiftUI
Apple определяет SwiftUI как новый способ создания пользовательских интерфейсов для платформ Apple, используя преимущества Swift.
Другое возможное определение для SwiftUI состоит в том, что это основа для создания пользовательских интерфейсов в декларативном стиле программирования с использованием Swift в форме предметно-ориентированного языка (DSL).
Как SwiftUI упрощает построение пользовательского интерфейса
Сегодня в подавляющем большинстве случаев построение пользовательского интерфейса включает использование Interface Builder, в котором вы устанавливаете компоненты пользовательского интерфейса и их расположение относительно друг друга. Затем эти компоненты привязываются к коду с помощью Outlets, Actions и т. Д. Таким образом, пользовательский интерфейс и его поведение по существу создаются в двух отдельных местах, что само по себе не очень удобно.
Альтернативой этому является создание пользовательского интерфейса в коде. Хотя на данный момент это еще более сложная задача. Например, вот как выглядит построение кнопок:
Как видно из приведенного выше фрагмента кода, необходимо учитывать множество нюансов:
- Вы должны установить угловой радиус для кнопки на ее CALayer вместо самой кнопки.
- Чтобы установить событие onclick, вам нужно создать селектор, и чтобы указать там функцию hello () , вы устанавливаете атрибут @objc для кнопки.
- Еще одна вещь, с которой вы должны быть знакомы, это создание ограничений.
Наряду со всеми трудностями, вы можете увидеть результаты только после запуска приложения.
Для сравнения, вот как вы создаете кнопку в SwiftUI:
Преимущество декларативного программирования SwiftUI состоит в том, что вы описываете желаемый результат, а не императивный подход, когда вам нужно установить последовательность конкретных действий для получения желаемого результата.
Как работает SwiftUI
Как уже упоминалось выше, SwiftUI использует DSL . Что именно является предметно-ориентированным языком? Это так называемый доменный язык, который позволяет описывать примитивы определенного конкретного домена на основе языка высокого уровня (в нашем случае это Swift). Затем с помощью этих примитивов решаются задачи, специфичные для предметной области. По сути, новый язык строится на основе старого.
В приведенном выше примере такими примитивами являются Button и Text.
Чтобы синтаксис SwiftUI был максимально простым и понятным, в Swift 5.1 были внесены некоторые изменения.
Вот некоторые из этих изменений:
- Построители функций [SE-XXXX]
Благодаря этому дополнению, такой синтаксис стал возможным:
Джава
xxxxxxxxxx
1
HStack {
2
Text("SwiftUI")
4
Text("rocks")
6
}
- Непрозрачные типы возврата [SE-0244]
Это позволяет вам возвращать протокол со связанным типом из функции и устраняет необходимость явного указания общих параметров возвращаемого типа:
Джава
xxxxxxxxxx
1
var body: some View {...}
SwiftUI использует это для привязки свойств объекта к View.
скомбинировать
Apple описывает Combine довольно просто как основу для настройки обработки асинхронных событий путем объединения операторов обработки событий.
Что стоит за этим описанием
Когда вы начинаете копаться в документации Combine и сталкиваетесь с такими техническими терминами, как Publisher, Subscriber, Operators, Cancellable и Scheduler , сразу становится ясно, что платформа Combine является в основном реализацией парадигмы функционального реактивного программирования (FRP) Apple .
Программисты iOS, знакомые с такими библиотеками, как RxSwift и ReactiveCocoa , сразу понимают, почему Combine был создан в первую очередь и какие задачи он должен был решать. Кроме того, с Combine больше не нужно использовать сторонние решения.
Какие задачи объединяет решает
Парадигма FRP в целом и Combine в частности повышает уровень абстракции кода. Это позволяет сосредоточиться на событиях, определяющих бизнес-логику приложения, вместо того, чтобы тратить время на изучение большого количества деталей реализации. Все это позволяет уменьшить объем стандартного кода ( DispatchQueues, Делегаты, KVO, Target-Actions и т. Д.).
Преимущества использования Combine Framework:
- Простой асинхронный код
- Многопоточность упрощена
- Составные компоненты бизнес-логики, которые можно легко объединить в цепочки
Допустим, нашему приложению необходимо выполнить 3 асинхронных запроса одновременно и получить результат выполнения.
Мы могли бы использовать DispatchGroup и DispatchQueue для решения этой сложной задачи. Для создания очереди, группировки, добавления задач в очередь и подписки на обратный вызов потребуется некоторый стандартный код. Все становится немного сложнее, если асинхронные задачи должны возвращать какой-то результат. В этом случае вам нужно будет создать переменные экземпляра и записать и прочитать значения оттуда.
Вот как выглядит решение в Combine:
Джава
xxxxxxxxxx
1
Publishers.Zip3(intAsyncTask, stringAsyncTask, voidAsyncTask)
2
.sink { (intValue, stringValue, _) in
3
// tasks executions are finished
4
}
Альтернатива более краткая. Это декларативный подход в действии. Вы можете сосредоточиться на том, что вам нужно, а не углубляться в изобилие деталей реализации.
SwiftUI + Combine
А теперь давайте посмотрим, что произойдет, если мы будем использовать SwiftUI и Combine рядом. Рассмотрим простой пример формы ввода имени пользователя.
Давайте определим ResetPasswordModel, который имеет только одно поле, принимающее пользовательский ввод.
Джава
xxxxxxxxxx
1
class ResetPasswordModel: ObservableObject {
2
var email = ""
3
}
- ResetPasswordModel соответствует протоколу ObservableObject , что означает, что поля ResetPasswordModel могут использоваться для привязок SwiftUI.
- @Published модификатор создает издатель для поля электронной почты, так что теперь можно наблюдать свойство электронной почты.
Во-вторых, давайте определим пользовательский интерфейс с SwiftUI.
Джава
xxxxxxxxxx
1
struct ResetPasswordView: View {
2
private var model = ResetPasswordModel()
4
var body: some View {
6
Form {
7
Section { TextField("Email", text: $model.email) }
8
}
9
}
- @ObservedObject является свойством делегата , который создает связь между видом и моделью . Представление уведомляется, когда источник данных собирается измениться и, следовательно, повторно отображать себя.
- $ model.email - $ sign здесь используется для создания оболочки свойств, которая обеспечивает двустороннюю привязку к данным, поэтому любые изменения значения электронной почты будут обновлять TextField , а любые изменения в TextField будут обновлять электронную почту.
Вывод
Похоже, что Apple проделала большую работу, предоставив нам инструменты, которые делают процесс создания пользовательского интерфейса более эффективным.
Декларативный подход нового SwiftUI обеспечивает ряд преимуществ, включая увеличенную скорость разработки, лучшую интеграцию между дизайнерами и программистами и повышение качества кода.
Используйте комбинированный эффект SwiftUI в сочетании с Combine для создания хорошо структурированного, эффективного и удобного в обслуживании кода.