SwiftUI — kernconcepten, View, State en Data Flow

Auteur: IT Sectr Gepubliceerd: 2026-02-21 Leestijd: 8 min

SwiftUI — Apple's declaratieve framework voor het bouwen van gebruikersinterfaces op alle platformen van het ecosysteem, geïntroduceerd op WWDC 2019. In tegenstelling tot het imperatieve UIKit met zijn viewDidLoad en handmatige schermvernieuwing, beschrijft SwiftUI UI als een verzameling eenvoudige structuren die voldoen aan het View-protocol. Volgens Swift.org (2025) wordt SwiftUI gebruikt in 65% van de nieuwe projecten die in de App Store zijn gepubliceerd. Het framework beheert automatisch de interface-updates via het State en Data Flow-mechanisme — wanneer gegevens veranderen, wordt View opnieuw getekend zonder handmatige aanroep van reloadData.

Belangrijkste punten

  • SwiftUI — Apple's declaratieve framework voor UI (2019), waarin de interface wordt beschreven met structuren die voldoen aan het View-protocol.
  • View — de basisbouwsteen van SwiftUI; elke View beschrijft zijn deel van het scherm via computed property body.
  • @State — property wrapper voor het opslaan van lokale toestand, bij verandering waarvan View automatisch opnieuw wordt getekend.
  • @Binding — tweerichtingsverbinding tussen View en gegevens, waarmee een kind-View de toestand van de ouder kan wijzigen.
  • @ObservedObject en @StateObject — verbinding met externe gegevensmodellen via klassen die voldoen aan het ObservableObject-protocol.

Wat is SwiftUI?

SwiftUI — Apple's declaratieve UI-framework, radicaal anders dan UIKit. In plaats van controllers, views en het handmatig beheren van hun levenscyclus, beschrijft de ontwikkelaar de interface in de vorm van declaraties: wat er op het scherm moet verschijnen, niet hoe het gebouwd moet worden. SwiftUI is gebaseerd op het principe van reactiviteit: de interface is een functie van de toestand. Bij verandering van toestand (State) herberekent SwiftUI automatisch de body van alle afhankelijke Views en werkt alleen de gewijzigde delen van het scherm bij. SwiftUI is beschikbaar op iOS 13+, iPadOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ en visionOS 1+. SwiftUI-code is cross-platform: één bestand werkt op iPhone, iPad, Mac en Apple Watch met minimale platformaanpassingen. Volgens Apple WWDC Session 101 (2024) dekt SwiftUI meer dan 90% van de standaard UI-patronen van de App Store.

SwiftUI vs UIKit

UIKit — het imperatieve framework (2008): de ontwikkelaar maakt een UIViewController, configureert subviews in viewDidLoad, implementeert delegate/datasource voor UITableView en werkt het scherm bij via reloadData of setNeedsLayout. SwiftUI vervangt controllers door eenvoudige View-structuren, delegaten door binding en onChange, Auto Layout door HStack/VStack/ZStack met modificatoren (padding, frame, offset). UIKit vereist handmatig geheugenbeheer via ARC; SwiftUI — structuren die geen referentietelling nodig hebben. De prestaties van SwiftUI zijn vergelijkbaar met UIKit: het framework gebruikt een diffing-algoritme voor een minimale set wijzigingen. Bij IT Sectr wordt SwiftUI gebruikt voor nieuwe projecten met iOS 17+ target; projecten met ondersteuning voor iOS 14–15 vereisen UIKit vanwege de beperkte compatibiliteit van SwiftUI.

Declaratieve syntaxis van SwiftUI

In SwiftUI wordt de interface beschreven via ViewBuilder — een result builder die een set Views transformeert naar een tuple of Group. Modificatoren (.padding(), .font(), .foregroundColor()) creëren nieuwe Views met gewijzigde instellingen, muteren niet het originele object. Elke modificator retourneert een nieuwe View, wat chaining mogelijk maakt. ViewBuilder ondersteunt if/else, switch, ForEach — conditionele en cyclische weergave zonder aparte controllers. View in SwiftUI is een value type (struct), wat voorspelbaar gedrag garandeert en race conditions elimineert.

Het View-protocol en computed property body

View — een protocol met één vereiste: computed property body van het type some View. Elke structuur die voldoet aan View beschrijft zijn deel van het scherm in body. Het type some View — opaque return type dat het concrete type van de geretourneerde View verbergt (samenstelling van VStack, HStack, ZStack, Text, Image enz.). De Swift-compiler leidt het concrete type af tijdens de compilatiefase, waardoor de prestaties van directe aanroep behouden blijven zonder type-uitwissing.

swift
import SwiftUI

struct GreetingView: View {
    var name: String
    
    var body: some View {
        VStack(spacing: 12) {
            Text("Hallo, \(name)!")
                .font(.largeTitle)
                .foregroundColor(.primary)
            
            Text("Welkom bij SwiftUI")
                .font(.body)
                .foregroundColor(.secondary)
        }
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(.ultraThinMaterial)
        )
    }
}

De structuur GreetingView accepteert de parameter name en toont twee tekstblokken in een verticale stack. De modificatoren .font, .foregroundColor, .padding en .background configureren het uiterlijk. SwiftUI roept body aan telkens wanneer de invoerparameters (name) veranderen — het opnieuw tekenen vindt alleen plaats voor de gewijzigde delen. In het voorbeeld wordt RoundedRectangle met .ultraThinMaterial gebruikt — native blur-achtergrond ingebouwd in SwiftUI.

@State: lokale toestand in SwiftUI

@State — een property wrapper die lokale toestand declareert die aan één View toebehoort. SwiftUI beheert het geheugen van State automatisch: bij verandering van de waarde wordt body opnieuw getekend, maar alleen voor Views die deze State gebruiken. State is de bron van waarheid (source of truth) voor eenvoudige typen (String, Int, Bool, enum). Gebruik @State niet voor complexe gegevensmodellen — daarvoor zijn @StateObject en @ObservedObject bedoeld. State moet private zijn en in de View zelf worden opgeslagen, niet worden doorgegeven tussen componenten.

swift
import SwiftUI

struct CounterView: View {
    @State private var count = 0
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Aantal: \(count)")
                .font(.system(size: 48, weight: .bold))
            
            Button(action: { count += 1 }) {
                Label("Verhoog", systemImage: "plus.circle")
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}

Beginwaarde count = 0. Elke druk op de knop verhoogt count; SwiftUI tekent CounterView automatisch volledig opnieuw (alle Views). In UIKit zou een vergelijkbaar scenario IBOutlet, IBAction en handmatige bijwerking van label.text hebben vereist. @State garandeert dat View alleen opnieuw wordt getekend bij verandering van een specifieke State — het diffing-algoritme van SwiftUI vindt minimale wijzigingen in de boomstructuur.

@Binding: tweerichtingscommunicatie tussen Views

@Binding — een property wrapper die een tweerichtingsverbinding creëert tussen een View en gegevens die de View niet beheert. Binding is een verwijzing naar State (of een andere bron van waarheid), waarmee een kind-View de waarde die in de ouder is opgeslagen kan lezen en wijzigen. Binding wordt aangeduid met het $-prefix: $count geeft Binding<Int> door aan de kind-View. Zonder Binding kan de kind-View de gegevens van de ouder niet wijzigen — alleen lezen.

swift
import SwiftUI

struct StepperControl: View {
    @Binding var value: Int
    let range: ClosedRange<Int>
    
    var body: some View {
        HStack {
            Button(action: { if value > range.lowerBound { value -= 1 } }) {
                Image(systemName: "minus.circle")
            }
            Text("\(value)")
                .frame(minWidth: 40)
            Button(action: { if value < range.upperBound { value += 1 } }) {
                Image(systemName: "plus.circle")
            }
        }
    }
}

struct ParentView: View {
    @State private var quantity = 5
    
    var body: some View {
        StepperControl(value: $quantity, range: 1...10)
    }
}

ParentView bezit de State quantity en geeft Binding door via $quantity. StepperControl kan value wijzigen, en quantity in de ouder wordt automatisch gesynchroniseerd. Binding is geen kopie van gegevens, maar een brug naar de bron van waarheid. Gebruik @Binding voor aangepaste besturingselementen, editors en herbruikbare componenten die gegevens van de ouder moeten wijzigen.

@ObservedObject en @StateObject: externe gegevensmodellen

@StateObject — een property wrapper voor het maken en bezitten van een instantie van een klasse die voldoet aan ObservableObject. De View maakt het object eenmaal per levenscyclus en wordt opnieuw getekend bij verandering van de @Published-eigenschappen. @ObservedObject — een vergelijkbare wrapper, maar de View bezit het object niet — het object wordt buiten de View gemaakt en opgeslagen (doorgegeven via de initialisator). Apple beveelt @StateObject aan voor de bron van waarheid in de View-hiërarchie en @ObservedObject voor het injecteren van afhankelijkheden.

swift
import SwiftUI
import Combine

class UserSettings: ObservableObject {
    @Published var username: String = "Guest"
    @Published var isLoggedIn = false
}

struct ProfileView: View {
    @StateObject private var settings = UserSettings()
    
    var body: some View {
        VStack {
            TextField("Username", text: $settings.username)
                .textFieldStyle(.roundedBorder)
            
            Toggle("Logged In", isOn: $settings.isLoggedIn)
            
            if settings.isLoggedIn {
                Text("Welkom, \(settings.username)!")
                    .font(.headline)
            }
        }
        .padding()
    }
}

UserSettings — een ObservableObject met twee @Published-eigenschappen. ProfileView bezit het object via @StateObject. Wijziging van username of isLoggedIn tekent ProfileView automatisch opnieuw. @Published gebruikt Combine Publisher om SwiftUI op de hoogte te stellen van wijzigingen. Gebruik @ObservedObject om settings door te geven aan kind-Views:

Data Flow in SwiftUI: het volledige beeld

Apple definieert vier niveaus van Data Flow in SwiftUI: @State (lokaal, value type), @Binding (tweerichtings), @StateObject/@ObservedObject (reference type met ObservableObject), @EnvironmentObject (globaal, injectie via omgeving). EnvironmentObject maakt het mogelijk gegevens door de hele View-hiërarchie te delen zonder expliciete overdracht in de initialisator. Daarnaast werkt @AppStorage met UserDefaults, @SceneStorage — met scène-toestand, @FetchRequest — met Core Data. De keuze van het Data Flow-niveau bepaalt de architectuur van de applicatie: eenvoudige schermen gebruiken State/Binding, modulaire — ObservedObject, grootschalige — EnvironmentObject + Redux-achtige oplossingen (TCA, Composable Architecture).

Property WrapperEigendomTypeWanneer gebruiken
@StateLokaalValue (struct, enum)Eenvoudige toestand van één View (teller, toggle, tekstveld)
@BindingExternVerwijzing naar StateKind-View dat gegevens van ouder wijzigt
@StateObjectView-bezitReference (class)Bron van waarheid voor complex gegevensmodel
@ObservedObjectInjectieReference (class)Model buiten View gemaakt (doorgegeven via init)
@EnvironmentObjectGlobaalReference (class)Gegevens toegankelijk voor hele hiërarchie (authenticatie, thema)

Veelgestelde vragen

Wat is het verschil tussen @State en @StateObject?

@State — voor value types (struct, enum, String, Int) en lokale toestand van één View. SwiftUI beheert het geheugen van State automatisch. @StateObject — voor reference types (class) die voldoen aan ObservableObject. @StateObject bezit het object en tekent de View opnieuw bij @Published-eigenschapswijzigingen. Gebruik @State voor eenvoudige tellers; voor modellen met logica — @StateObject.

Kan SwiftUI met UIKit worden gebruikt?

Ja, SwiftUI integreert met UIKit via UIHostingController (SwiftUI binnen UIKit) en UIViewRepresentable (UIKit binnen SwiftUI). UIHostingController wikkelt een SwiftUI View in een UIViewController. UIViewRepresentable maakt het mogelijk UIKit-componenten (MKMapView, WKWebView) in SwiftUI te gebruiken. Dit is de standaardaanpak voor migratie van projecten van UIKit naar SwiftUI.

Wat is ViewBuilder in SwiftUI?

ViewBuilder — een result builder (Swift 5.1) die een set Views transformeert naar één waarde van het type TupleView, Group of ConditionalContent. ViewBuilder maakt het mogelijk imperatieve if/else en switch binnen een declaratieve body te schrijven. Zonder ViewBuilder zou voor elk conditioneel blok AnyView of Group moeten worden geretourneerd. ViewBuilder is de reden waarom in body geen komma tussen Views nodig is.

Werkt SwiftUI op alle Apple-apparaten?

Ja, SwiftUI ondersteunt iOS 13+, iPadOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ en visionOS 1+. Sommige API's zijn echter alleen beschikbaar op nieuwere versies: bijvoorbeeld navigationStack (iOS 16+), Observable macro (iOS 17+). Gebruik #available en UIKit-aanpassingen voor achterwaartse compatibiliteit.

Hoe debug ik SwiftUI-applicaties?

Xcode Debug View Hierarchy toont de SwiftUI View-boom met modificatoren en frames. Het hulpprogramma SwiftUI Inspector (rechterpaneel van Xcode) maakt het mogelijk modificatoren in real-time te wijzigen. self._printChanges() in body logt de oorzaken van hertekening. Instruments met het SwiftUI-sjabloon traceert View-prestaties en detecteert overmatige hertekeningen.

Samenvatting

  • SwiftUI — Apple's declaratieve framework voor UI, waarin de interface wordt beschreven met View-structuren met computed property body (2019).
  • View — value type (struct) dat voldoet aan het View-protocol; body retourneert some View via ViewBuilder.
  • @State — lokale toestand voor value types; bij wijziging wordt View automatisch opnieuw getekend.
  • @Binding — tweerichtingsverbinding via $-prefix; kind-View wijzigt gegevens van ouder.
  • @StateObject / @ObservedObject — reference types met ObservableObject en @Published-eigenschappen; StateObject bezit het object, ObservedObject ontvangt van buitenaf.
  • @EnvironmentObject — globale toestand voor de hele View-hiërarchie; geïnjecteerd via .environmentObject().
  • Data Flow in SwiftUI — van State (lokaal) via Binding (tweerichtings) naar ObservedObject (modulair) en EnvironmentObject (globaal).

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.

Bespreek het project

Lees ook