De eigenschap body — het centrale element van het View-protocol in SwiftUI dat bepaalt welke inhoud op het scherm wordt weergegeven. Volgens Apple Developer Documentation, 2024 is body de enige verplichte vereiste van het View-protocol en retourneert het een type dat aan dit protocol voldoet. SwiftUI roept body aan bij elke statuswijziging om een nieuwe elementenboom te bouwen en te vergelijken.
Belangrijkste punten
body — is een berekende eigenschap (computed property) die de enige verplichte vereiste is van het View-protocol. Elke structuur die voldoet aan View moet body implementeren. De eigenschap retourneert de inhoud die SwiftUI op het scherm weergeeft — dit kan tekst, afbeelding, knop, container met geneste elementen of elk ander type zijn dat voldoet aan het View-protocol.
De handtekening van body is altijd vast: var body: some View { get }. Het retourtype is some View (ondoorzichtig type), niet een concreet type. Dit betekent dat verschillende View verschillende concrete typen kunnen retourneren in body, maar de Swift-compiler stelt het concrete type voor elke implementatie vast in de compilatiefase.
Volgens WWDC 2022 is body het toegangspunt tot de declaratieve beschrijving van de interface. In tegenstelling tot UIKit, waar u imperatief UIView maakt en configureert, beschrijft u in SwiftUI declaratief wat er moet worden weergegeven en berekent SwiftUI zelf hoe dit te implementeren.
body moet zich gedragen als een pure functie — met dezelfde invoergegevens (structuureigenschappen en status) moet het dezelfde View-boom retourneren. Als body afhankelijk is van externe veranderlijke status (globale variabelen, UserDefaults zonder @AppStorage-omhulsel), wordt het gedrag onvoorspelbaar en kan SwiftUI het scherm onjuist opnieuw tekenen.
Berekende eigenschap body slaat geen waarde op — het wordt elke keer berekend wanneer het wordt benaderd. Wanneer SwiftUI bepaalt dat de status is gewijzigd, wordt de View-structuur opnieuw aangemaakt en wordt de nieuwe waarde van body gelezen om de geactualiseerde elementenboom voor weergave te verkrijgen.
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Teller: \(count)")
.font(.largeTitle)
Button("Verhogen") {
count += 1
}
.padding()
.background(.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
}
In dit voorbeeld retourneert body een VStack met Text en een knop met aanpassingen. Bij het indrukken van de knop wordt de @State-eigenschap count verhoogd, maakt SwiftUI de CounterView-structuur opnieuw aan en roept opnieuw body aan om de geactualiseerde boom met de nieuwe waarde van Text te verkrijgen.
Aanpassingen (.font, .padding, .background, .foregroundColor, .cornerRadius) wijzigen de oorspronkelijke View niet, maar wikkelen deze in ModifiedContent — een nieuw type dat de aanpassing toevoegt. Elke aanpassing creëert een extra niveau van nesting, wat belangrijk is voor de prestaties.
some View in het retourtype van body — is niet alleen een conventie, maar een verplichte vereiste van de compiler. Swift vereist dat alle retourpaden in body hetzelfde concrete type hebben. Zonder @ViewBuilder kunt u niet Text in de ene tak en Button in de andere retourneren — de compiler geeft een foutmelding.
struct ConditionalView: View {
var isReady: Bool
@ViewBuilder
var body: some View {
if isReady {
Text("Klaar")
.foregroundColor(.green)
} else {
ProgressView()
}
}
}
@ViewBuilder op body maakt het mogelijk om conditionele logica (if/else, switch) te gebruiken zonder compilatiefouten. ViewBuilder wikkelt automatisch verschillende takken in ConditionalContent — een speciaal type dat de verschillen van concrete typen verbergt. Dit is een belangrijke mogelijkheid voor het bouwen van dynamische interfaces.
Zonder @ViewBuilder probeert de compiler een uniform type af te leiden voor alle retourpaden. Als de typen verschillend zijn — treedt er een fout op. Daarom past SwiftUI impliciet @ViewBuilder toe op body in View-declaraties, hoewel in gebruikerscode de annotatie expliciet moet worden geplaatst voor aangepaste methoden en eigenschappen die meerdere View retourneren.
Het gebruik van some View in plaats van een concreet type vermindert de prestaties niet — de compiler kent in de compilatiefase het exacte type en genereert directe code zonder dynamische dispatche. AnyView daarentegen gebruikt type-uitwissing (type erasure) met overhead voor verpakking in een existentiële container.
body wordt door SwiftUI aangeroepen in drie hoofscenario's: bij de eerste weergave van View, bij wijziging van @State/@Binding/@ObservedObject/@StateObject en bij wijziging van de bovenliggende View die nieuwe waarden doorgeeft via de initialisator. SwiftUI kan ook body aanroepen bij wijziging van omgevingswaarden (@Environment).
De frequentie van het aanroepen van body hoeft u geen zorgen te baren — SwiftUI optimaliseert het opnieuw tekenen via het identiteitsmechanisme. Elke View in de hiërarchie heeft een unieke identificatie. Als de identiteit en invoergegevens niet zijn gewijzigd — wordt body niet aangeroepen, zelfs niet als de bovenliggende View opnieuw is getekend. Dit wordt bereikt door Equatable-vergelijking en stabiliteit van structuren.
struct ParentView: View {
var body: some View {
ChildView(name: "Alice") // Stabiele identiteit
}
}
struct ChildView: View {
let name: String
var body: some View {
Text("Hallo, \(name)!")
}
}
In dit voorbeeld, als ParentView opnieuw wordt getekend maar dezelfde waarde van name doorgeeft — wordt ChildView.body niet aangeroepen. SwiftUI vergelijkt de invoergegevens van de structuur en als deze niet zijn gewijzigd, wordt het opnieuw tekenen van de component overgeslagen. Dit is het mechanisme van View-differentiatie (view differentiation).
Er zijn verschillende valkuilen die leiden tot onverwacht aanroepen van body: gebruik van klassen zonder ObservableObject, doorgeven van closures die binnen body worden gemaakt (elke creatie van een closure geeft een nieuwe identiteit) en onjuist gebruik van EquatableView. Als body te vaak wordt aangeroepen — controleer de identiteitsstabiliteit van alle onderliggende componenten.
Eerste regel: body moet minimaal zijn. Haal complexe logica naar aparte berekende eigenschappen of methoden die View retourneren. Dit verbetert de leesbaarheid en stelt SwiftUI in staat nauwkeuriger te bepalen welke delen van de hiërarchie zijn gewijzigd. Verdeel grote body's in subcomponenten met duidelijke verantwoordelijkheidsgrenzen.
Tweede regel: gebruik body niet om werk uit te voeren. Gegevens laden, netwerkwerk, database schrijven — dit alles moet buiten body plaatsvinden, in taken (task), onChange-aanpassingen of via ObservableObject. body is uitsluitend bedoeld voor de declaratie van de interface.
Derde regel: gebruik de eigenschap EquatableView of een aangepast Equatable-protocol voor View, als de standaard vergelijking van structuren niet voldoende is. Hiermee kunt u expliciet aangeven aan SwiftUI wanneer een onderliggende View opnieuw moet worden getekend en onnodige body-aanroepen voorkomen.
Vierde regel: als body complexe berekeningen bevat (formattering, filtering, sortering) — gebruik @State voor caching van het resultaat of haal de berekeningen naar een aparte methode die vanuit onChange wordt aangeroepen. Herhaalde berekeningen in body bij elke statusupdate — een veelvoorkomende oorzaak van animatievertragingen.
Vijfde regel: zorg voor lijsten (List, ForEach) voor stabiele identificaties via de parameter id. Zonder stabiele identiteit maakt ForEach alle elementen opnieuw aan bij elke wijziging, waarbij body voor elk ervan wordt aangeroepen, zelfs als slechts één element is gewijzigd.
Veelgestelde vragen
body — de berekende eigenschap van het View-protocol die de weer te geven inhoud retourneert. Dit is de enige verplichte vereiste van het protocol. Het retourtype is some View, waarmee SwiftUI de hiërarchie in de compilatiefase kan optimaliseren.
Ja, SwiftUI roept body aan bij elke statuswijziging (@State, @Binding, @ObservedObject) of invoergegevens. Dit is normaal gedrag van een declaratief framework. SwiftUI optimaliseert de aanroeptijd via het identiteitsmechanisme en Equatable-vergelijking.
some View — een ondoorzichtig type waarmee u de concrete implementatie kunt verbergen. De compiler stelt het type vast in de compilatiefase, wat de prestaties van directe aanroep garandeert. Dit biedt flexibiliteit: u kunt het retourtype wijzigen zonder de handtekening te veranderen.
Nee, body kan niet optioneel zijn — het retourtype some View staat nil niet toe. Als u een element voorwaardelijk wilt verbergen, gebruik dan conditionele logica binnen @ViewBuilder of retourneer EmptyView, dat geen ruimte inneemt in de hiërarchie.
Elke aanpassing creëert een nieuwe laag ModifiedContent, waardoor de diepte van de hiërarchie toeneemt. Voor de meeste schermen (tot 50 aanpassingen) is de impact onmerkbaar. Een overmatig aantal aanpassingen (honderden) kan de diffing vertragen. Groepeer gerelateerde aanpassingen in aangepaste extensies.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook