@ViewBuilder: cos'è, result builder per View in SwiftUI

Autore: IT Sectr Pubblicato: 2026-06-24 Tempo di lettura: 7 min

@ViewBuilder è un'annotazione result builder in SwiftUI progettata per la costruzione dichiarativa di gerarchie di View. Secondo Apple Developer Documentation, 2024, @ViewBuilder trasforma un blocco di codice con multiple espressioni e logica condizionale in un unico tipo View comprensibile al compilatore Swift. Senza questa annotazione, sarebbe impossibile utilizzare la familiare sintassi dichiarativa di SwiftUI con if/else e molteplici elementi nel body.

Punti chiave

  • @ViewBuilder — result builder che compone più Views in una composizione senza contenitori extra
  • buildBlock — avvolge una sequenza di espressioni in TupleView fino a 10 elementi
  • buildEither — crea ConditionalContent per rami if/else e switch
  • Limitazione — fino a 10 elementi in un singolo blocco senza Group o ForEach
  • Applicazione implicita — body è già avvolto in @ViewBuilder, le funzioni personalizzate richiedono annotazione esplicita

Cos'è @ViewBuilder in SwiftUI?

@ViewBuilder è un'annotazione che implementa il pattern result builder (SE-0289), che consente a SwiftUI di comporre più Views in un'unica composizione usando la sintassi dichiarativa. Avvolge automaticamente espressioni multiple, costrutti condizionali e valori opzionali nei loro tipi corrispondenti: TupleView, ConditionalContent, OptionalContent.

Prima dell'arrivo dei result builder, gli sviluppatori dovevano avvolgere manualmente gli elementi in VStack o HStack e usare operatori ternari o metodi factory per la logica condizionale. @ViewBuilder ha reso la sintassi di SwiftUI concisa e leggibile, permettendo di scrivere codice che assomiglia a Swift normale con if/else e cicli.

Secondo Swift Evolution SE-0289, i result builder sono un meccanismo generale non legato a SwiftUI. @ViewBuilder è un'implementazione di questo meccanismo, insieme a @StringBuilder per la costruzione di stringhe e implementazioni libreria per altri DSL. In SwiftUI, @ViewBuilder è utilizzato non solo per body, ma anche per i parametri closure dei contenitori (VStack, HStack, ZStack, List).

Differenza dall'approccio imperativo

Nell'UIKit imperativo, crei esplicitamente un UIView, configuri le sue proprietà e lo aggiungi alla gerarchia tramite addSubview. In SwiftUI con @ViewBuilder, descrivi dichiarativamente quali Views devono essere visualizzate, e SwiftUI gestisce la creazione, l'aggiornamento e la rimozione degli elementi in base ai cambiamenti di stato.

Come funziona @ViewBuilder: result builder

Result builder è un meccanismo di Swift che trasforma una sequenza di espressioni in un unico valore composito attraverso i metodi statici buildBlock, buildOptional, buildEither e altri. Quando il compilatore vede l'annotazione @ViewBuilder, applica automaticamente questi metodi al blocco di codice durante la compilazione.

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 accetta da 1 a 10 espressioni e restituisce un TupleView. Ogni arità (numero di espressioni) ha il proprio overload di buildBlock: da buildBlock a buildBlock. Questo è il motivo per cui il numero di elementi in un singolo blocco @ViewBuilder è limitato a 10.

buildEither (first/second) gestisce i costrutti if/else. Ogni ramo viene passato al metodo corrispondente e il risultato viene avvolto in ConditionalContent — un tipo che nasconde i tipi specifici dei rami e fornisce un'interfaccia unificata per SwiftUI.

Comportamento implicito di @ViewBuilder

In SwiftUI, la proprietà body è già implicitamente annotata con @ViewBuilder — non vedi questa annotazione nel codice, ma il compilatore la applica automaticamente. Tuttavia, per proprietà personalizzate che restituiscono più Views, o per parametri closure, l'annotazione deve essere specificata esplicitamente.

Limitazioni di @ViewBuilder e come evitarle

Limitazione 1 — 10 elementi in un blocco. Questa è la limitazione più nota di @ViewBuilder. Se devi visualizzare più di 10 elementi allo stesso livello, il compilatore emetterà un errore. Le soluzioni includono Group, ForEach, List o la suddivisione in sottocomponenti. Group non aggiunge annidamento visivo, ma ogni Group conta come un elemento.

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")
        }
    }
}

Limitazione 2 — mancanza di supporto per alcuni costrutti. @ViewBuilder non supporta do/catch, guard, for-in (senza ForEach) e altri costrutti di controllo del flusso. Per i cicli, usa ForEach con dati identificabili. Per la gestione degli errori, usa Views separate che accettano Result o valori opzionali.

Limitazione 3 — complessità di debug. Quando si verificano errori in @ViewBuilder, il compilatore produce messaggi verbosi in cui è difficile trovare la causa principale. Problemi tipici: mancata corrispondenza dei tipi nei rami if/else, superamento del limite di 10 elementi o mancanza degli overload necessari di buildBlock.

Pattern di utilizzo di @ViewBuilder

Pattern 1: visualizzazione condizionale tramite if/else. Il caso d'uso più comune di @ViewBuilder. Permette di mostrare diverse Views in base allo stato senza usare operatori ternari o metodi factory.

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)
        }
    }
}

Pattern 2: @ViewBuilder nei parametri di funzioni e inizializzatori. Utilizzato per creare contenitori riutilizzabili che accettano Views figlie tramite una closure. Questo è il pattern standard per librerie e componenti UI.

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)
    }
}

Pattern 3: composizione con ForEach. @ViewBuilder funziona correttamente con ForEach, permettendo la generazione dinamica di elementi da un array di dati. Ogni elemento di ForEach conta come un'espressione nel contesto di @ViewBuilder.

Creazione di un ViewBuilder personalizzato per componenti riutilizzabili

ViewBuilder personalizzato è una funzione o proprietà definita dall'utente annotata con @ViewBuilder che restituisce some View. Queste funzioni permettono di incapsulare logica di visualizzazione complessa e riutilizzarla in diverse parti dell'applicazione.

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
        }
    }
}

// Utilizzo:
FormRow(label: "Name") {
    TextField("Enter name", text: $name)
}

FormRow(label: "Gender") {
    Picker("Select", selection: $gender) {
        Text("Maschio").tag(Gender.male)
        Text("Femmina").tag(Gender.female)
    }
}

Regola importante: una funzione personalizzata con @ViewBuilder deve restituire some View, non un tipo concreto o il protocollo View. Solo un tipo opaco permette di nascondere l'implementazione concreta preservando la flessibilità di composizione.

Prestazioni: le funzioni personalizzate @ViewBuilder non aggiungono overhead rispetto al codice diretto in body. Il compilatore inlinea le chiamate e ottimizza il codice risultante. Dividere body in funzioni @ViewBuilder migliora la leggibilità senza sacrificare le prestazioni.

Domande frequenti

Cos'è @ViewBuilder in SwiftUI?

@ViewBuilder è un'annotazione result builder che trasforma un blocco di codice con multiple espressioni e condizioni in un unico tipo View. Permette di usare la sintassi Swift familiare (if/else, switch, espressioni opzionali) all'interno dell'UI dichiarativa di SwiftUI.

Perché non si possono mettere più di 10 elementi in @ViewBuilder?

La limitazione deriva dall'implementazione di buildBlock — esiste un overload separato del metodo per ogni arità da 1 a 10. Swift non supporta i generics variadici, quindi il numero di overload è fisso. Per aggirarlo, usa Group, ForEach o sottocomponenti.

Devo specificare esplicitamente @ViewBuilder prima di body?

No, il protocollo View applica implicitamente @ViewBuilder alla proprietà body. Tuttavia, per proprietà personalizzate, metodi e parametri closure che restituiscono più Views, l'annotazione deve essere specificata esplicitamente. Senza di essa, il compilatore non sarà in grado di gestire espressioni multiple.

Come gestisce @ViewBuilder le espressioni opzionali?

Per le espressioni opzionali, viene usato il metodo buildIf, che accetta una View opzionale e la restituisce se esiste un valore. Se il valore è nil, buildIf restituisce nil e l'elemento non viene visualizzato. Questo permette di usare if let all'interno del body.

Si può usare @ViewBuilder con switch?

Sì, da Swift 5.9 @ViewBuilder supporta switch tramite il metodo buildExpression. Il compilatore trasforma ogni ramo case nella corrispondente chiamata buildEither. Il supporto di switch rende il codice più leggibile rispetto ai costrutti if/else annidati.

Riepilogo

  • @ViewBuilder — result builder per la costruzione dichiarativa di gerarchie View in SwiftUI
  • buildBlock avvolge una sequenza di espressioni in TupleView (fino a 10 elementi)
  • buildEither crea ConditionalContent per rami if/else e switch
  • buildIf gestisce espressioni opzionali e if senza else
  • Group e ForEach aiutano a evitare il limite di 10 elementi per blocco
  • Funzioni @ViewBuilder personalizzate migliorano la riutilizzabilità senza perdita di prestazioni
  • @ViewBuilder è applicato implicitamente a body, ma richiede annotazione esplicita per i parametri

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche