Добавить объявление

Result Builders в SwiftUI: как создать свой DSL

Привет, друзья! В прошлый раз мы разбирали @ViewBuilder, а сегодня углубимся в его основу и поговорим про resultBuilder, который делает магию SwiftUI возможной.

Что такое resultBuilder:


Result Builder (ранее назывался function builder) - это механизм, позволяющий:

  • Объединять элементы в единую структуру.

  • Создавать собственные мини-языки (DSL) прямо в Swift.

  • Писать декларативный код, как в SwiftUI.

Как работает в SwiftUI:


Когда вы пишете:

VStack {
Text("Привет")

Button("Нажми меня") {
// Действие
}
}

Под капотом @ViewBuilder (частный случай Result Builder) превращает это в TupleView.

Создаем свой Result Builder:


Сделаем билдер для объединения строк с отступами:

@resultBuilder
struct ParagraphBuilder {
// Объединяем строки через \n
static func buildBlock(_ components: String...) -> String {
components.map { "- \($0)" }.joined(separator: "\n")
}

// Поддержка if
static func buildOptional(_ component: String?) -> String {
component ?? ""
}
}

// Использование:
@ParagraphBuilder func makeList() -> String {
"Первый пункт"
"Второй пункт"

if true {
"Случайный пункт"
}
}

print(makeList())

/* Выведет:
- Первый пункт
- Второй пункт
- Случайный пункт
*/

Где еще применяется:



Кастомные UI-билдеры:

Например, для декларативного описания таблиц:

@TableBuilder func buildTable() -> Table {
Row {
Cell("A1")
Cell("A2")
}
Row {
Cell("B1")
Cell("B2")
}
}


Конфигурация сетевых запросов:

@RequestBuilder func makeRequest() -> HTTPRequest {
Method(.get)
Path("users")
Query("page", "2")
}


Тестовые данные:

@TestDataBuilder func mockUser() -> User {
Name("Иван")
Age(30)

if isPremium {
Tier(.gold)
}
}

Ограничения:


  • Нет поддержки for-циклов (нужно реализовывать buildArray).

  • Сложная отладка (ошибки компиляции могут быть непонятными).

  • Лимит в 10 элементов (как у @ViewBuilder).

Вывод:


Result Builder - это мощный инструмент Swift, позволяющий создавать собственные DSL-синтаксисы для декларативного описания логики. Он лежит в основе @ViewBuilder и открывает возможности для кастомных решений, но требует внимания к ограничениям вроде обработки условий и лимита элементов.
09.08.2025 20 419