@ViewBuilder: co to je, result builder pro View v SwiftUI

Autor: IT Sectr Publikováno: 2026-06-24 Doba čtení: 7 min

@ViewBuilder — je anotace result builderu v SwiftUI, určená pro deklarativní vytváření hierarchie View. Podle Apple Developer Documentation, 2024, převádí @ViewBuilder blok kódu s více výrazy a podmíněnou logikou na jediný typ View, srozumitelný pro kompilátor Swift. Bez této anotace by nebylo možné používat známou deklarativní syntaxi SwiftUI s if/else a několika prvky v těle body.

Hlavní body

  • @ViewBuilder — result builder, který spojuje několik View do kompozice bez zbytečných kontejnerů
  • buildBlock — zabalí sekvenci výrazů do TupleView až do 10 prvků
  • buildEither — vytváří ConditionalContent pro větve if/else a switch
  • Omezení — až 10 prvků v jednom bloku bez Group nebo ForEach
  • Implicitní použití — body je již zabaleno v @ViewBuilder, uživatelské funkce vyžadují explicitní anotaci

Co je @ViewBuilder v SwiftUI?

@ViewBuilder — je anotace implementující vzor result builder (SE-0289), která umožňuje SwiftUI shromáždit několik View do jedné kompozice pomocí deklarativní syntaxe. Automaticky zabalí více výrazů, podmíněné konstrukce a volitelné hodnoty do odpovídajících typů: TupleView, ConditionalContent, OptionalContent.

Před příchodem result builderu museli vývojáři ručně zabalovat prvky do VStack nebo HStack a pro podmíněnou logiku používat ternární operátory nebo tovární metody. @ViewBuilder učinil syntaxi SwiftUI výstižnou a čitelnou, umožňujíc psaní kódu, který vypadá jako běžný Swift s if/else a cykly.

Podle Swift Evolution SE-0289 jsou result builders obecným mechanismem, který není vázán na SwiftUI. @ViewBuilder je jednou z implementací tohoto mechanismu, vedle @StringBuilder pro vytváření řetězců a knihovních implementací pro jiné DSL. V SwiftUI se @ViewBuilder používá nejen pro body, ale také pro parametry uzávěrů kontejnerů (VStack, HStack, ZStack, List).

Rozdíl oproti imperativnímu přístupu

V imperativním UIKit imperativně vytváříte UIView, konfigurujete jeho vlastnosti a přidáváte jej do hierarchie přes addSubview. V SwiftUI s @ViewBuilder deklarativně popisujete, která View mají být zobrazena, a SwiftUI sám spravuje vytváření, aktualizaci a odstraňování prvků na základě změn stavu.

Jak funguje @ViewBuilder: result builder

Result builder — je mechanismus Swift, který převádí sekvenci výrazů na jedinou složenou hodnotu prostřednictvím statických metod buildBlock, buildOptional, buildEither a dalších. Když kompilátor uvidí anotaci @ViewBuilder, automaticky aplikuje tyto metody na blok kódu během kompilace.

swift
@resultBuilder
struct ViewBuilder {
    static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)>
    static func buildIf<C>(_ c: C?) -> C?
    static func buildEither<T, F>(first: T) -> ConditionalContent<T, F>
    static func buildEither<T, F>(second: F) -> ConditionalContent<T, F>
}

buildBlock přijímá 1 až 10 výrazů a vrací TupleView. Každá arita (počet výrazů) má svůj vlastní overload buildBlock: od buildBlock<C0> do buildBlock<C0, C1, ..., C9>. Právě proto je počet prvků v jednom bloku @ViewBuilder omezen na 10.

buildEither (first/second) zpracovává konstrukce if/else. Každá větev je předána odpovídající metodě a výsledek je zabalen do ConditionalContent — typu, který skrývá konkrétní typy větví a poskytuje jednotné rozhraní pro SwiftUI.

Implicitní práce @ViewBuilder

V SwiftUI je vlastnost body již implicitně anotována @ViewBuilder — tuto anotaci v kódu nevidíte, ale kompilátor ji automaticky aplikuje. Pro uživatelské vlastnosti vracející více View nebo pro parametry uzávěrů je však třeba anotaci explicitně uvést.

Omezení @ViewBuilder a jak je obejít

Omezení 1 — 10 prvků v bloku. Toto je nejznámější omezení @ViewBuilder. Pokud potřebujete zobrazit více než 10 prvků na jedné úrovni, kompilátor vyvolá chybu. Lze to obejít pomocí Group, ForEach, List nebo rozdělením na podkomponenty. Group nepřidává vizuální vnoření, ale každý Group se počítá jako jeden prvek.

swift
struct ManyElementsView: View {
    var body: some View {
        Group {
            Text("1"); Text("2"); Text("3")
            Text("4"); Text("5"); Text("6")
            Text("7"); Text("8"); Text("9")
        }
        Group {
            Text("10"); Text("11"); Text("12")
        }
    }
}

Omezení 2 — nedostatek podpory pro některé konstrukce. @ViewBuilder nepodporuje do/catch, guard, for-in (bez ForEach) a další řídicí konstrukce. Pro cykly používejte ForEach s identifikovatelnými daty. Pro zpracování chyb používejte samostatná View přijímající Result nebo volitelné hodnoty.

Omezení 3 — obtížnost ladění. Při chybách v @ViewBuilder generuje kompilátor rozsáhlé zprávy, ve kterých je obtížné najít hlavní příčinu. Typické problémy: nesoulad typů ve větvích if/else, překročení limitu 10 prvků nebo chybějící požadovaný overload buildBlock.

Vzory použití @ViewBuilder

Vzor 1: podmíněné zobrazení pomocí if/else. Nejčastější scénář použití @ViewBuilder. Umožňuje zobrazovat různá View v závislosti na stavu bez použití ternárních operátorů nebo továrních metod.

swift
struct StatusView: View {
    var status: LoadStatus

    @ViewBuilder
    var body: some View {
        switch status {
        case .loading:
            ProgressView("Loading...")
        case .loaded(let data):
            DataView(data: data)
        case .error(let message):
            ErrorView(message: message)
        }
    }
}

Vzor 2: @ViewBuilder v parametrech funkcí a inicializátorů. Používá se pro vytváření znovupoužitelných kontejnerů, které přijímají podřízená View prostřednictvím uzávěru. Toto je standardní vzor pro knihovny a UI komponenty.

swift
struct SectionCard<Content: View>: View {
    let title: String
    @ViewBuilder let content: Content

    var body: some View {
        VStack(alignment: .leading) {
            Text(title).font(.headline)
            content
        }
        .padding()
        .background(Color.gray.opacity(0.1))
        .cornerRadius(12)
    }
}

Vzor 3: kompozice s ForEach. @ViewBuilder správně pracuje s ForEach, umožňujíc dynamické generování prvků z pole dat. Každý prvek ForEach se počítá jako jeden výraz v kontextu @ViewBuilder.

Vytvoření vlastního ViewBuilder pro znovupoužitelné komponenty

Vlastní ViewBuilder — je uživatelská funkce nebo vlastnost anotovaná @ViewBuilder, která vrací some View. Takové funkce umožňují zapouzdřit složitou logiku zobrazení a znovu ji použít v různých částech aplikace.

swift
struct FormRow<Content: View>: View {
    let label: String
    @ViewBuilder let content: Content

    var body: some View {
        HStack {
            Text(label)
                .frame(width: 120, alignment: .trailing)
            content
        }
    }
}

// Použití:
FormRow(label: "Name") {
    TextField("Enter name", text: $name)
}

FormRow(label: "Gender") {
    Picker("Select", selection: $gender) {
        Text("Muž").tag(Gender.male)
        Text("Žena").tag(Gender.female)
    }
}

Důležité pravidlo: vlastní funkce s @ViewBuilder musí vracet some View, nikoli konkrétní typ nebo protokol View. Pouze opaque typ umožňuje skrýt konkrétní implementaci a zachovat flexibilitu kompozice.

Výkon: vlastní funkce @ViewBuilder nepřidávají režii ve srovnání s přímým kódem v body. Kompilátor inlineuje volání a optimalizuje výsledný kód. Rozdělení body na funkce @ViewBuilder zlepšuje čitelnost bez ztráty výkonu.

Často kladené otázky

Co je @ViewBuilder v SwiftUI?

@ViewBuilder — je anotace result builderu, která převádí blok kódu s více výrazy a podmínkami na jediný typ View. Umožňuje používat známou syntaxi Swift (if/else, switch, volitelné výrazy) uvnitř deklarativního UI SwiftUI.

Proč nelze do @ViewBuilder umístit více než 10 prvků?

Omezení souvisí s implementací buildBlock — pro každou aritu od 1 do 10 existuje samostatný overload metody. Swift nepodporuje variadic generics, takže počet overloadů je pevný. Pro obejití použijte Group, ForEach nebo podkomponenty.

Je nutné explicitně uvádět @ViewBuilder před body?

Ne, protokol View implicitně aplikuje @ViewBuilder na vlastnost body. Pro uživatelské vlastnosti, metody a parametry uzávěrů vracející více View je však třeba anotaci explicitně uvést. Bez ní kompilátor nebude schopen zpracovat více výrazů.

Jak @ViewBuilder zpracovává volitelné výrazy?

Pro volitelné výrazy se používá metoda buildIf, která přijímá volitelný View a vrací jej, pokud hodnota existuje. Pokud je hodnota nil — buildIf vrací nil a prvek se nezobrazí. To umožňuje použití if let v těle body.

Lze @ViewBuilder použít s switch?

Ano, od Swift 5.9 @ViewBuilder podporuje switch prostřednictvím metody buildExpression. Kompilátor převádí každou větev case na odpovídající volání buildEither. Podpora switch dělá kód čitelnějším ve srovnání s vnořenými konstrukcemi if/else.

Shrnutí

  • @ViewBuilder — result builder pro deklarativní vytváření hierarchie View v SwiftUI
  • buildBlock zabalí sekvenci výrazů do TupleView (až 10 prvků)
  • buildEither vytváří ConditionalContent pro větve if/else a switch
  • buildIf zpracovává volitelné výrazy a if bez else
  • Group a ForEach pomáhají obejít omezení 10 prvků na blok
  • Vlastní funkce @ViewBuilder zlepšují znovupoužitelnost bez ztráty výkonu
  • @ViewBuilder je implicitně aplikován na body, ale vyžaduje explicitní anotaci pro parametry

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také