SwiftUI — Apples deklaratives Framework zur Erstellung von Benutzeroberflächen auf allen Plattformen des Ökosystems, vorgestellt auf der WWDC 2019. Im Gegensatz zum imperativen UIKit mit seinem viewDidLoad und manuellen Bildschirmaktualisierungen beschreibt SwiftUI die UI als eine Sammlung einfacher Strukturen, die dem View-Protokoll entsprechen. Laut Swift.org (2025) wird SwiftUI in 65% der neuen, im App Store veröffentlichten Projekte verwendet. Das Framework verwaltet UI-Updates automatisch über den State- und Data-Flow-Mechanismus — wenn sich Daten ändern, wird die View ohne manuelle reloadData-Aufrufe neu gezeichnet.
Wichtige Erkenntnisse
SwiftUI — Apples deklaratives UI-Framework, das sich grundlegend von UIKit unterscheidet. Anstatt Controller und Views zu erstellen und deren Lebenszyklus manuell zu verwalten, beschreibt der Entwickler die Oberfläche als Deklarationen: was auf dem Bildschirm sein soll, nicht wie es erstellt wird. SwiftUI basiert auf dem Prinzip der Reaktivität: Die Oberfläche ist eine Funktion des Zustands. Wenn sich der Zustand ändert, berechnet SwiftUI automatisch den Body aller abhängigen Views neu und aktualisiert nur die geänderten Teile des Bildschirms. SwiftUI ist verfügbar für iOS 13+, iPadOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ und visionOS 1+. SwiftUI-Code ist plattformübergreifend: Eine Datei funktioniert auf iPhone, iPad, Mac und Apple Watch mit minimalen Plattformanpassungen. Laut Apple WWDC Session 101 (2024) deckt SwiftUI über 90% der Standard-UI-Muster im App Store ab.
UIKit — imperatives Framework (2008): Der Entwickler erstellt einen UIViewController, konfiguriert Subviews in viewDidLoad, implementiert delegate/datasource für UITableView und aktualisiert den Bildschirm über reloadData oder setNeedsLayout. SwiftUI ersetzt Controller durch einfache View-Strukturen, Delegaten durch Bindings und onChange, Auto Layout durch HStack/VStack/ZStack mit Modifikatoren (padding, frame, offset). UIKit erfordert manuelle Speicherverwaltung über ARC; SwiftUI verwendet Strukturen, die keine Referenzzählung benötigen. Die Leistung von SwiftUI ist mit UIKit vergleichbar: Das Framework verwendet einen Diffing-Algorithmus für minimale Änderungssätze. Bei IT Sectr wird SwiftUI für neue Projekte mit iOS 17+ Ziel verwendet; Projekte mit iOS 14–15-Unterstützung benötigen aufgrund der eingeschränkten SwiftUI-Kompatibilität UIKit.
In SwiftUI wird die Oberfläche über ViewBuilder beschrieben — einen Result Builder, der eine Menge von Views in ein Tupel oder Group umwandelt. Modifikatoren (.padding(), .font(), .foregroundColor()) erstellen neue Views mit geänderten Einstellungen, anstatt das ursprüngliche Objekt zu mutieren. Jeder Modifikator gibt eine neue View zurück, was Verkettung ermöglicht. ViewBuilder unterstützt if/else, switch, ForEach — bedingte und zyklische Darstellung ohne separate Controller. View in SwiftUI ist ein Value Type (struct), was vorhersehbares Verhalten gewährleistet und Wettlaufsituationen ausschließt.
View — ein Protokoll mit einer einzigen Anforderung: die computed property body vom Typ some View. Jede Struktur, die View entspricht, beschreibt ihren Bildschirmteil im body. Der Typ some View ist ein opaker Rückgabetyp, der den konkreten Typ der zurückgegebenen View verbirgt (Stapelung von VStack, HStack, ZStack, Text, Image usw.). Der Swift-Compiler leitet den konkreten Typ zur Kompilierzeit ab und bewahrt die Leistung direkter Aufrufe ohne Typ-Löschung.
import SwiftUI
struct GreetingView: View {
var name: String
var body: some View {
VStack(spacing: 12) {
Text("Hallo, \(name)!")
.font(.largeTitle)
.foregroundColor(.primary)
Text("Willkommen bei SwiftUI")
.font(.body)
.foregroundColor(.secondary)
}
.padding()
.background(
RoundedRectangle(cornerRadius: 12)
.fill(.ultraThinMaterial)
)
}
}Die Struktur GreetingView nimmt einen Parameter name entgegen und zeigt zwei Textblöcke in einem vertikalen Stack an. Die Modifikatoren .font, .foregroundColor, .padding und .background konfigurieren das Erscheinungsbild. SwiftUI ruft body jedes Mal auf, wenn sich die Eingabeparameter (name) ändern — die Neuzeichnung erfolgt nur für die geänderten Teile. Das Beispiel verwendet RoundedRectangle mit .ultraThinMaterial — einem nativen Unschärfe-Hintergrund, der in SwiftUI integriert ist.
@State — ein Property Wrapper, der einen lokalen Zustand deklariert, der zu einer einzelnen View gehört. SwiftUI verwaltet den State-Speicher automatisch: Wenn sich der Wert ändert, wird der Body neu gezeichnet, aber nur für Views, die diesen State verwenden. State ist die Source of Truth für einfache Typen (String, Int, Bool, enum). Verwenden Sie @State nicht für komplexe Datenmodelle — verwenden Sie stattdessen @StateObject und @ObservedObject. State sollte privat sein und innerhalb der View selbst gespeichert werden, nicht zwischen Komponenten übergeben werden.
import SwiftUI
struct CounterView: View {
@State private var count = 0
var body: some View {
VStack(spacing: 20) {
Text("Zählung: \(count)")
.font(.system(size: 48, weight: .bold))
Button(action: { count += 1 }) {
Label("Erhöhen", systemImage: "plus.circle")
}
.buttonStyle(.borderedProminent)
}
.padding()
}
}Der anfängliche count-Wert = 0. Jeder Tastendruck erhöht count; SwiftUI zeichnet automatisch die gesamte CounterView (alle Views) neu. In UIKit hätte ein ähnliches Szenario IBOutlet, IBAction und manuelle label.text-Aktualisierungen erfordert. @State stellt sicher, dass eine View nur neu gezeichnet wird, wenn sich ein bestimmter State ändert — der Diffing-Algorithmus von SwiftUI findet die minimalen Änderungen im Baum.
@Binding — ein Property Wrapper, der eine bidirektionale Verbindung zwischen einer View und Daten herstellt, die die View nicht besitzt. Ein Binding ist ein Verweis auf State (oder eine andere Source of Truth), der es einer Child-View ermöglicht, den im Parent gespeicherten Wert zu lesen und zu ändern. Binding wird durch das $-Präfix gekennzeichnet: $count übergibt ein Binding<Int> an die Child-View. Ohne Binding kann eine Child-View die Daten des Parents nicht ändern — sie kann sie nur lesen.
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 besitzt den State quantity und übergibt Binding über $quantity. StepperControl kann den Wert ändern, und quantity im Parent wird automatisch synchronisiert. Ein Binding ist keine Kopie der Daten, sondern eine Brücke zur Source of Truth. Verwenden Sie @Binding für benutzerdefinierte Steuerelemente, Editoren und wiederverwendbare Komponenten, die die Daten des Parents ändern müssen.
@StateObject — ein Property Wrapper zum Erstellen und Besitzen einer Instanz einer Klasse, die ObservableObject entspricht. Die View erstellt das Objekt einmal pro Lebenszyklus und wird neu gezeichnet, wenn sich ihre @Published-Eigenschaften ändern. @ObservedObject — ein ähnlicher Wrapper, aber die View besitzt das Objekt nicht — das Objekt wird außerhalb der View erstellt und gespeichert (über einen Initialisierer übergeben). Apple empfiehlt @StateObject für die Source of Truth in einer View-Hierarchie und @ObservedObject für die Abhängigkeitsinjektion.
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("Willkommen, \(settings.username)!")
.font(.headline)
}
}
.padding()
}
}UserSettings — ein ObservableObject mit zwei @Published-Eigenschaften. ProfileView besitzt das Objekt über @StateObject. Änderungen an username oder isLoggedIn zeichnen ProfileView automatisch neu. @Published verwendet Combine Publisher, um SwiftUI über Änderungen zu benachrichtigen. Um settings an Child-Views zu übergeben, verwenden Sie @ObservedObject:
Apple definiert vier Ebenen des Data Flow in SwiftUI: @State (lokal, Value Type), @Binding (bidirektional), @StateObject/@ObservedObject (Reference Type mit ObservableObject), @EnvironmentObject (global, über die Umgebung injiziert). EnvironmentObject ermöglicht die Datenübergabe durch die gesamte View-Hierarchie ohne explizite Übergabe im Initialisierer. Zusätzlich arbeitet @AppStorage mit UserDefaults, @SceneStorage mit dem Szenenzustand, @FetchRequest mit Core Data. Die Wahl der Data Flow-Ebene bestimmt die Anwendungsarchitektur: Einfache Bildschirme verwenden State/Binding, modulare verwenden ObservedObject, groß angelegte verwenden EnvironmentObject + Redux-ähnliche Lösungen (TCA, Composable Architecture).
| Property Wrapper | Eigentum | Typ | Verwendungszweck |
|---|---|---|---|
| @State | Lokal | Value (struct, enum) | Einfacher Zustand einer einzelnen View (Zähler, Schalter, Textfeld) |
| @Binding | Extern | Verweis auf State | Child-View ändert Daten des Parents |
| @StateObject | View-Besitz | Reference (class) | Source of Truth für komplexes Datenmodell |
| @ObservedObject | Injektion | Reference (class) | Außerhalb der View erstelltes Modell (über init übergeben) |
| @EnvironmentObject | Global | Reference (class) | Für gesamte Hierarchie verfügbare Daten (Auth, Theme) |
Häufig gestellte Fragen
@State — für Value Types (struct, enum, String, Int) und lokalen Zustand einer einzelnen View. SwiftUI verwaltet den State-Speicher automatisch. @StateObject — für Reference Types (class), die ObservableObject entsprechen. @StateObject besitzt das Objekt und zeichnet die View neu, wenn sich @Published-Eigenschaften ändern. Für einfache Zähler verwenden Sie @State; für Modelle mit Geschäftslogik verwenden Sie @StateObject.
Ja, SwiftUI integriert sich mit UIKit über UIHostingController (SwiftUI in UIKit) und UIViewRepresentable (UIKit in SwiftUI). UIHostingController kapselt eine SwiftUI View in einem UIViewController. UIViewRepresentable ermöglicht die Verwendung von UIKit-Komponenten (MKMapView, WKWebView) in SwiftUI. Dies ist der Standardansatz für die Migration von Projekten von UIKit zu SwiftUI.
ViewBuilder — ein Result Builder (Swift 5.1), der eine Menge von Views in einen einzelnen Wert vom Typ TupleView, Group oder ConditionalContent umwandelt. ViewBuilder ermöglicht das Schreiben von imperativem if/else und switch innerhalb eines deklarativen body. Ohne ViewBuilder müsste man für jeden Bedingungsblock AnyView oder Group zurückgeben. ViewBuilder ist der Grund, warum body keine Kommas zwischen Views benötigt.
Ja, SwiftUI unterstützt iOS 13+, iPadOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ und visionOS 1+. Allerdings sind einige APIs nur auf neueren Versionen verfügbar: zum Beispiel navigationStack (iOS 16+), Observable macro (iOS 17+). Verwenden Sie für Abwärtskompatibilität #available und UIKit-Adaptionen.
Xcode Debug View Hierarchy zeigt den SwiftUI View-Baum mit Modifikatoren und Rahmen. Das SwiftUI Inspector-Tool (rechtes Xcode-Panel) ermöglicht das Ändern von Modifikatoren in Echtzeit. self._printChanges() im Body protokolliert die Gründe für die Neuzeichnung. Instruments mit der SwiftUI-Vorlage verfolgt die View-Leistung und identifiziert übermäßige Neuzeichnungen.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch