Как SwiftUI позволяет возвращать несколько view из свойства body без явного контейнера?

Ответ

Эта возможность обеспечивается атрибутом @ViewBuilder, который неявно применяется к свойству body.

Принцип работы:

  1. @ViewBuilder — это function builder, который преобразует последовательность выражений вида View в единую коллекцию представлений.
  2. Компилятор автоматически оборачивает несколько view, возвращаемых из body, в специальный тип — TupleView.

Пример и преобразование:

// Код разработчика (чистый синтаксис):
var body: some View {
    Text("Hello")
    Text("World")
    Image(systemName: "globe")
}

// Фактически компилятор генерирует:
var body: some View {
    ViewBuilder.buildBlock(
        Text("Hello"),
        Text("World"),
        Image(systemName: "globe")
    ) // Возвращает TupleView<(Text, Text, Image)>
}

Важные ограничения:

  • Логика (if, switch) внутри body также поддерживается ViewBuilder.
  • Максимальное количество view в такой неявной группе — 10 (ограничение кортежей в Swift). Для большего числа или динамических списков используйте явные контейнеры: Group, VStack, ForEach.
    // Для >10 элементов или динамического списка:
    var body: some View {
    Group { // или VStack
        // ... более 10 представлений
    }
    }

Ответ 18+ 🔞

Да ты посмотри, какая хитрая жопа у SwiftUI! Вот пишешь ты в body три строчки, а компилятор смотрит на это и думает: «Ага, чувак, ты тут накидал видюшек, щас я тебе покажу, как это на самом деле работает!»

Весь фокус в этом самом @ViewBuilder. Это такой, блядь, function builder, который берёт твою простыню из Text и Image и заворачивает её в один аккуратный пиздючок — TupleView.

Как это, сука, происходит: Ты пишешь вот так, наивный:

var body: some View {
    Text("Hello")
    Text("World")
    Image(systemName: "globe")
}

А компилятор, хитрожопый, делает под капотом вот это:

var body: some View {
    ViewBuilder.buildBlock(
        Text("Hello"),
        Text("World"),
        Image(systemName: "globe")
    ) // Возвращает ёбаный TupleView<(Text, Text, Image)>
}

Но есть, блядь, подвох! У этого TupleView есть лимит — 10 штук максимум. Потому что кортежи в Swift больше десяти не тянут, ёпта! Если тебе нужно больше или список динамический — не выёбывайся, бери явные контейнеры: Group или VStack.

// Больше десяти? Получай Group, мудила!
var body: some View {
    Group { // или VStack, если тебе по вертикали надо
        // ... сюда пихай свои овердохуища представлений
    }
}

А логику (if, switch) внутри body он тоже проглатывает, потому что ViewBuilder и это умеет. В общем, штука мощная, но со своими тараканами. Главное — лимит в десять штук не перепрыгнуть, а то получишь ошибку и волнение ебать.