Najważniejsze punkty
View Protocol to centralny protokół SwiftUI. Wymaga tylko jednej właściwości: var body: some View. body to właściwość obliczana zwracająca opis interfejsu. SwiftUI wywołuje body przy każdej zmianie stanu i renderuje wynik na GPU.
@ViewBuilder to Result Builder dla View. Pozwala pisać wiele Views wewnątrz closure bez return i bez TupleView. Obsługuje if/else, switch, ForEach. Wszystkie kontenery (VStack, HStack, ZStack, Group) używają @ViewBuilder. Alternatywą jest Group { … } do grupowania bez układu. some View to Opaque Type. Kompilator zna konkretny typ View (Text, Button, VStack itp.), ale zwraca go zewnętrznie jako some View. Pozwala to zmienić typ body bez zmiany sygnatury. ViewModifier — modyfikator View: .font(), .padding(), .background(). Niestandardowy modyfikator przez ViewModifier protocol i .modifier().
// Przykład View z @ViewBuilder i NavigationStack
struct ContentView: View {
@State private var items = ["Item 1", "Item 2"]
var body: some View {
NavigationStack {
List(items, id: .self) { item in
NavigationLink(item) {
DetailView(item: item)
}
}
.navigationTitle("Items")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
items.append("New Item")
}
}
}
}
}
}
// DetailView z @StateObject
struct DetailView: View {
let item: String
@StateObject private var viewModel = DetailViewModel()
var body: some View {
Text(item)
.task {
await viewModel.loadDetails(for: item)
}
}
}NavigationStack (iOS 16+) — nawigacja oparta na danych. Przyjmuje ścieżkę (tablicę wartości hashable) i wyświetla miejsce docelowe przez navigationDestination. Zastępuje NavigationLink z widokami docelowymi. NavigationLink — przycisk do nawigacji w stosie. List — pionowa lista z sekcjami, przesunięciami, usuwaniem i przeciąganiem. Form — wyspecjalizowana List dla ustawień: sekcje, selektory, przełączniki, pola tekstowe. Section — grupowanie w List/Form z nagłówkiem i stopką. ViewModifier — niestandardowe modyfikatory do ponownego używania stylów. .modifier(CustomModifier()) — zastosowanie.
List w SwiftUI to odpowiednik UITableView. Obsługuje .onDelete, .onMove, .refreshable. SwipeActions — .swipeActions { Button("Usuń", role: .destructive) { } }. Form — zoptymalizowany dla ustawień: DatePicker, Toggle, Stepper, Picker. Section z header/footer — do grupowania. OutlineGroup — listy hierarchiczne (odpowiednik UITableView z sekcjami). DisclosureGroup — zwijana sekcja z zawartością. IT Sectr zaleca List dla danych i Form dla ustawień.
PreviewProvider — protokół dla podglądów w Xcode Canvas. Canvas — interaktywny podgląd SwiftUI (wymaga @main i Swift 5.9+). @ScaledMetric — adaptacyjny rozmiar skalujący się z Dynamic Type.
Property Wrappers to podstawa zarządzania stanem w SwiftUI. @State — stan lokalny (typ wartości). @Binding — połączenie ze stanem rodzica. @StateObject — tworzy ObservableObject. SwiftUI zarządza cyklem życia obiektu. @ObservedObject — obserwuje zewnętrzny ObservableObject. @EnvironmentObject — obiekt ze środowiska (wstrzykiwanie zależności przez .environmentObject()). @Environment — wartości systemowe (.colorScheme, .locale). @AppStorage — UserDefaults. @FetchRequest — zapytanie Core Data. @FocusState — fokus wprowadzania.
| Wrapper | Przeznaczenie | Własność |
|---|---|---|
| @State | Stan lokalny (typ wartości) | View posiada |
| @Binding | Połączenie ze stanem rodzica | Rodzic posiada |
| @StateObject | Tworzenie ObservableObject | View posiada |
| @ObservedObject | Obserwacja zewnętrznego obiektu | Zewnętrzny właściciel |
| @EnvironmentObject | Obiekt ze środowiska | Przodek posiada |
| @Environment | Wartość systemowa | System |
| @AppStorage | UserDefaults | UserDefaults |
| @FocusState | Fokus wprowadzania | View posiada |
@StateObject vs @ObservedObject: @StateObject tworzy obiekt, @ObservedObject go obserwuje. Użyj @StateObject do pierwszego tworzenia modelu w hierarchii, @ObservedObject do przekazywania widokom potomnym. @FocusState — zarządzanie fokusem: .focused($field, equals: .email). Obsługuje enum dla wielu pól.
@Environment — wartości systemowe: colorScheme, locale, sizeCategory, layoutDirection, managedObjectContext. Niestandardowe wartości środowiskowe — niestandardowa wartość przez EnvironmentKey. Używane do wstrzykiwania zależności: przekazywanie usług bez jawnych parametrów. Modyfikator .environment() — ustawia wartość w hierarchii. @EnvironmentObject — ObservableObject z .environmentObject(). Różni się od @Environment tym, że przekazuje typ referencyjny. IT Sectr zaleca @Environment dla wartości systemowych i @EnvironmentObject dla usług.
.task{} — operacja asynchroniczna przy pojawieniu się widoku. Automatyczne anulowanie przy zniknięciu. Zastępuje .onAppear dla async/await. .onAppear{} — operacja synchroniczna przy pojawieniu. .onDisappear{} — operacja przy zniknięciu. .onChange(of:) — reakcja na zmiany wartości. .onReceive(Publisher) — reakcja na publisher Combine. Cykl życia View w SwiftUI: init → onAppear → body (renderowanie) → onDisappear. Przy zmianie stanu: body → diff → ponowne renderowanie. IT Sectr zaleca .task dla ładowania asynchronicznego i .onAppear dla analityki.
.animation() — modyfikator animacji. .transition() — animacja pojawiania/znikania. withAnimation — jawna animacja zmian stanu. matchedGeometryEffect — animacja między różnymi widokami (hero animation). PhaseAnimator (iOS 17+) — wielofazowa animacja oparta na enum. KeyframeAnimator (iOS 17+) — animacja klatka po klatce z klatkami kluczowymi. Animacje SwiftUI są wykonywane na GPU przez Core Animation. IT Sectr zaleca .spring() dla naturalnych animacji i .interpolatingSpring dla efektów fizycznych.
ObservableObject — protokół dla obiektów z właściwościami @Published. SwiftUI subskrybuje publisher objectWillChange. @Published — publikuje zmiany właściwości. @StateObject — tworzy ObservableObject, zarządza cyklem życia. @ObservedObject — obserwuje zewnętrzny. Combine — framework do programowania reaktywnego. @EnvironmentObject — DI przez środowisko. .environmentObject() ustawia, @EnvironmentObject czyta. MVVM — standardowa architektura: View (SwiftUI) — ViewModel (ObservableObject) — Model. IT Sectr zaleca MVVM + @StateObject dla głównych ViewModel.
class UserViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
func loadUsers() async {
isLoading = true
defer { isLoading = false }
do {
users = try await api.fetchUsers()
} catch {
print("Błąd: \(error)")
}
}
}
struct UsersView: View {
@StateObject private var viewModel = UserViewModel()
var body: some View {
List(viewModel.users, id: \.id) { user in
Text(user.name)
}
.task { await viewModel.loadUsers() }
.overlay {
if viewModel.isLoading { ProgressView() }
}
}
}Dostępność w SwiftUI: .accessibilityLabel(), .accessibilityHint(), .accessibilityValue(), .accessibilityAddTraits(). VoiceOver czyta etykiety dostępności. Dynamic Type — @ScaledMetric, @DynamicProperty. Lokalizacja: String(localized:) (SwiftUI + String Catalog). LocalizedStringKey — automatyczne tłumaczenie. Reguły liczby mnogiej — przez String Catalog (one, few, many, other). Od prawej do lewej (arabski, hebrajski) — obsługiwane automatycznie. .environment(.layoutDirection, .rightToLeft). IT Sectr zaleca etykiety dostępności dla wszystkich elementów interaktywnych.
struct AccessibleButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
Label("Settings", systemImage: "gear")
}
.accessibilityLabel("Open Settings")
.accessibilityHint("Double tap to navigate to settings screen")
.accessibilityAddTraits(.isButton)
}
}
// Obsługa Dynamic Type
struct ScalableText: View {
@ScaledMetric private var fontSize: CGFloat = 17
var body: some View {
Text("Hello, World!")
.font(.system(size: fontSize))
}
}Swift Charts (iOS 16+) — framework do tworzenia wykresów. Chart { } — podstawowy kontener. BarMark, LineMark, PointMark, AreaMark, RuleMark — znaczniki. ForEach dla danych. ChartAxis — dostosowywanie osi. .chartXAxis, .chartYAxis. ChartLegend — legenda. Interpolacja — catmullRom, linear, step. Animacja — .animation() dla Chart. IT Sectr zaleca Swift Charts dla wbudowanych wykresów i Charts (DGCharts) dla złożonych.
import Charts
struct MonthlySales: Identifiable {
let id = UUID()
let month: String
let sales: Double
}
struct SalesChart: View {
let data: [MonthlySales]
var body: some View {
Chart(data) { item in
BarMark(
x: .value("Month", item.month),
y: .value("Sales", item.sales)
)
.foregroundStyle(.blue.gradient)
}
.chartXAxisLabel("Month")
.chartYAxisLabel("Sales")
.frame(height: 200)
.padding()
}
}Swift Package Manager (SPM) — menedżer zależności Apple. Zintegrowany z Xcode. Obsługuje: pakiety binarne, zasoby, testy, ścisłą współbieżność swift-6. Publikowanie pakietów przez GitHub z tagiem semver. SPM to de facto standard dla zależności Swift, wypierający CocoaPods i Carthage. IT Sectr zaleca SPM dla wszystkich nowych projektów.
Swift Concurrency (async/await, TaskGroup, AsyncSequence) — async/await wbudowane w Swift 5.5+. Task — jednostka asynchroniczności. TaskGroup — równoległe zadania. AsyncSequence — sekwencja asynchroniczna (AsyncStream, AsyncAlgorithms). Task Local Values — dane kontekstowe dla Task. Swift Concurrency całkowicie zastępuje Combine dla operacji asynchronicznych.
Często zadawane pytania
View Protocol to podstawowy protokół. Wymaga var body: some View. body to opis interfejsu renderowany na GPU.
@ViewBuilder to Result Builder dla wielu Views. Pozwala na if/else, switch, ForEach w kontenerach.
@StateObject tworzy obiekt. @ObservedObject obserwuje istniejący. @StateObject do pierwszego utworzenia w hierarchii.
NavigationStack — nawigacja oparta na danych. path-based, deep linking. Zastępuje NavigationView.
@FocusState — zarządzanie fokusem wprowadzania. Modyfikator .focused(). Obsługuje enum dla wielu pól.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.