Powiązanie view modeli z widokami
Łączenie view modeli z SwiftUI i Combine.
Powiązanie view modeli z widokami to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.
Łączenie ViewModelu z Widokiem
ViewModel jest użyteczny tylko wtedy, gdy Widok reaguje na jego zmiany. W SwiftUI za tę reaktywność odpowiadają oparte na Combine property wrappers: @Published, @StateObject i @ObservedObject.
Razem tworzą automatyczne wiązanie: gdy ViewModel się zmienia, Widok jest renderowany ponownie.
ObservableObject
Aby SwiftUI mogło go obserwować, ViewModel musi być zgodny z protokołem ObservableObject. Protokół ten udostępnia publisher objectWillChange, który emituje powiadomienie przed każdą zmianą.
final class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}Właściwości @Published
Oznaczenie właściwości za pomocą @Published automatycznie emituje powiadomienie o zmianie za każdym razem, gdy zostanie ustawiona jej wartość.
Każda właściwość @Published zasila publisher objectWillChange obiektu, dzięki czemu Widok dokładnie wie, kiedy należy go odświeżyć.
final class SearchViewModel: ObservableObject {
@Published var query: String = ""
@Published var results: [String] = []
}@StateObject
@StateObject informuje Widok, że ma utworzyć ViewModel i zarządzać jego cyklem życia. SwiftUI tworzy go raz i zachowuje między kolejnymi renderowaniami tego Widoku.
@StateObject należy używać w miejscu, w którym ViewModel jest tworzony po raz pierwszy.
struct CounterView: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
Button("Count: \(viewModel.count)") {
viewModel.increment()
}
}
}@ObservedObject
@ObservedObject służy do obsługi ViewModelu utworzonego w innym miejscu i przekazanego do Widoku. Widok go obserwuje, ale nie zarządza jego cyklem życia.
Należy używać go w widokach podrzędnych, które otrzymują ViewModel od widoku nadrzędnego.
struct BadgeView: View {
@ObservedObject var viewModel: CounterViewModel
var body: some View {
Text("Total: \(viewModel.count)")
}
}StateObject a ObservedObject
Kluczowa różnica dotyczy własności:
- @StateObject — Widok jest jego właścicielem; obiekt przetrwa ponowne renderowanie
- @ObservedObject — obiekt jest przekazywany; Widok nie jest jego właścicielem
Użycie @ObservedObject w miejscu, w którym należy użyć @StateObject, może spowodować ponowne tworzenie obiektu i utratę jego stanu przy każdej aktualizacji widoku nadrzędnego.
Przekazywanie ViewModelu do widoków podrzędnych
Należy utworzyć ViewModel raz za pomocą @StateObject w widoku nadrzędnym, a następnie przekazać go widokom podrzędnym, które oznaczą go za pomocą @ObservedObject.
struct ParentView: View {
@StateObject private var viewModel = CounterViewModel()
var body: some View {
VStack {
BadgeView(viewModel: viewModel)
Button("Add") { viewModel.increment() }
}
}
}Wiązania dwukierunkowe
W przypadku pól tekstowych potrzebne jest dwukierunkowe Binding. SwiftUI tworzy je na podstawie właściwości @Published za pomocą prefiksu $ przy wrapperze.
struct SearchView: View {
@StateObject private var viewModel = SearchViewModel()
var body: some View {
TextField("Search", text: $viewModel.query)
}
}Sterowanie stanem interfejsu
Widok powinien wyprowadzać wszystko, co wyświetla, z opublikowanych właściwości. Wskaźniki ładowania, banery błędów i zawartość — wszystko wynika ze stanu ViewModelu.
final class FeedViewModel: ObservableObject {
enum State { case loading, loaded([String]), error(String) }
@Published var state: State = .loading
}Reagowanie na stan
Widok przełącza się na podstawie stanu ViewModelu, aby renderować właściwy interfejs użytkownika. Nie ma tu imperatywnego kodu pokazującego i ukrywającego elementy, lecz jedynie deklaratywne odwzorowanie.
struct FeedView: View {
@StateObject var viewModel = FeedViewModel()
var body: some View {
switch viewModel.state {
case .loading: ProgressView()
case .loaded(let items): List(items, id: \.self) { Text($0) }
case .error(let message): Text(message)
}
}
}Utrzymywanie aktualizacji w głównym wątku
SwiftUI wymaga, aby zmiany opublikowanych właściwości zachodziły w głównym wątku. Gdy ViewModel aktualizuje stan po zakończeniu pracy asynchronicznej, należy oznaczyć go za pomocą @MainActor, aby to zagwarantować.
@MainActor
final class ProfileViewModel: ObservableObject {
@Published var name: String = ""
func load() async {
name = await fetchName()
}
}Szybkie sprawdzenie
Sprawdź swoją wiedzę o wiązaniach.
Podsumowanie
Połączono ViewModel z Widokiem za pomocą wiązań SwiftUI:
- ObservableObject + @Published emitują powiadomienia o zmianach
- @StateObject tworzy ViewModel i zarządza jego cyklem życia
- @ObservedObject obserwuje przekazany ViewModel
- @MainActor utrzymuje aktualizacje asynchroniczne w głównym wątku
Dzięki reaktywnym wiązaniom Widok zawsze automatycznie odzwierciedla najnowszy stan ViewModelu.
Często zadawane pytania
Czy lekcja „Powiązanie view modeli z widokami” jest bezpłatna?
Tak — pełny tekst „Powiązanie view modeli z widokami” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Powiązanie view modeli z widokami”?
Łączenie view modeli z SwiftUI i Combine. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Swift Academy?
Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Powiązanie view modeli z widokami”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?
Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Wzorzec MVVM
- Powiązanie view modeli z widokami
- Wzorzec Coordinator
- Testowanie view modeli