@Statevə@Binding-in fərqini izah etmək və vahid həqiqət mənbəyini tapmaq@Observablemakrosu ilə model sinfi yaratmaq və onu@Stateilə saxlamaq@Environmentvə@Bindableilə modeli görünüşlər arasında paylaşmaq- SwiftUI-də MVVM qatlarını təsvir etmək
Nigar parametrlər ekranında gündəlik məqsədini 15 dəqiqədən 30-a qaldırır, amma əsas ekranda hələ də «15 min» yazılıb. Səbəb sadədir: eyni qiymət iki yerdə saxlanılıb və onlar bir-birindən xəbərsizdir. SwiftUI-də qızıl qayda belədir: hər məlumatın bir sahibi — vahid həqiqət mənbəyi olmalıdır, qalan görünüşlər isə onu oxumalı və ya ona bağlanmalıdır. Bu dərsdə bunun üçün alətləri öyrənəcəksən.
@State: görünüşün öz vəziyyəti
View strukturu dəyişməzdir və SwiftUI onu istənilən an yenidən yarada bilər. Ona görə dəyişən qiymət adi xassədə saxlanıla bilməz. @State SwiftUI-dən qiyməti strukturdan kənarda saxlamağı və dəyişəndə body-ni yenidən hesablamağı xahiş edir. @State xassəsini həmişə private elan et: o, yalnız bu görünüşə məxsusdur. İlkin qiymət yalnız bir dəfə, görünüş ekranda ilk dəfə yarananda götürülür; sonra SwiftUI öz saxladığı qiymətdən istifadə edir.
struct CounterView: View {
var count = 0
var body: some View {
Button("Taps: \(count)") {
count += 1
}
}
}struct CounterView: View {
@State private var count = 0
var body: some View {
Button("Taps: \(count)") {
count += 1
}
}
}@Binding: başqasının vəziyyətinə bağlantı
Uşaq görünüş valideynin qiymətini dəyişməlidirsə, ona surət yox, binding — iki tərəfli bağlantı verilir. Valideyn qiyməti $ ilə ötürür ($goal), uşaq isə onu @Binding kimi elan edir. Uşaq qiyməti dəyişəndə əslində valideynin @State-i dəyişir və ekranın hər iki hissəsi eyni anda yenilənir.
struct GoalStepper: View {
@Binding var minutes: Int
var body: some View {
Stepper("Daily goal: \(minutes) min", value: $minutes, in: 5...60, step: 5)
}
}
struct SettingsScreen: View {
@State private var goal = 15
var body: some View {
Form {
GoalStepper(minutes: $goal)
Text("You will study \(goal) minutes a day")
}
}
}+/− düyməli sətir və altında mətn; düyməyə basanda hər iki sətirdəki rəqəm birlikdə dəyişir.Məlumatın saxlandığı yeganə yer. Nümunədə bu, SettingsScreen-dəki @State private var goal-dur; GoalStepper isə yalnız ona bağlanır və öz surətini saxlamır.
@Observable modellər
Ekranın məlumatı və məntiqi çoxalanda onları ayrıca model sinfinə köçürürük. iOS 17-dən başlayaraq sinfin qarşısına @Observable makrosunu yazmaq kifayətdir: SwiftUI body-də oxunan xassələri özü izləyir və yalnız onlar dəyişəndə görünüşü yeniləyir. Modelin məntiqini ekransız, adi Swift kodu ilə də yoxlamaq olar:
import Observation
@Observable
final class QuizModel {
var question = 1
var score = 0
var finished: Bool { question > 5 }
func answer(correct: Bool) {
if correct { score += 1 }
question += 1
}
}
let quiz = QuizModel()
for correct in [true, false, true, true, true] {
quiz.answer(correct: correct)
}
print("Score: \(quiz.score) / 5, finished: \(quiz.finished)")Score: 4 / 5, finished: true
struct QuizView: View {
@State private var quiz = QuizModel()
var body: some View {
VStack(spacing: 16) {
if quiz.finished {
Text("Your score: \(quiz.score) / 5")
} else {
Text("Question \(quiz.question) of 5")
Button("Correct") { quiz.answer(correct: true) }
Button("Wrong") { quiz.answer(correct: false) }
}
}
.font(.title2)
}
}final class QuizModel: ObservableObject {
@Published var score = 0
}
struct QuizView: View {
@StateObject private var quiz = QuizModel()
// child views: @ObservedObject, @EnvironmentObject
}@Observable
final class QuizModel {
var score = 0
}
struct QuizView: View {
@State private var quiz = QuizModel()
// child views: plain property, @Bindable, @Environment
}@Published yazmaq lazım idi və obyektin istənilən dəyişikliyi onu izləyən bütün görünüşləri yeniləyirdi. @Observable daha az kod tələb edir və yalnız həqiqətən oxunan xassələrə reaksiya verir.@Environment və @Bindable
Modeli beş səviyyə aşağıdakı görünüşə parametrlər zənciri ilə ötürmək yorucudur. Bunun əvəzinə onu .environment(profile) ilə mühitə qoyuruq, lazım olan görünüş isə @Environment(Profile.self) private var profile ilə götürür. Modelin xassəsinə binding lazımdırsa (məsələn, TextField üçün), @Bindable işlədilir. @Environment həm də sistem qiymətlərini verir: \.dismiss, \.colorScheme, \.locale.
@Observable
final class Profile {
var name = "Nigar"
}
struct ProfileEditor: View {
@Bindable var profile: Profile
var body: some View {
TextField("Name", text: $profile.name)
}
}
struct GreetingView: View {
@Environment(Profile.self) private var profile
var body: some View {
Text("Hello, \(profile.name)!")
}
}@State private var profile = Profile() saxlayır və .environment(profile) çağırır. Sahədə adı dəyişəndə «Hello, …!» yazısı dərhal yenilənir.| Vasitə | Nə vaxt |
|---|---|
@State | görünüş qiymətin və ya @Observable modelin sahibidir |
@Binding | uşaq valideynin qiymətini oxuyur və dəyişir |
@Bindable | @Observable modelin xassələrinə binding lazımdır |
@Environment | sistem qiymətini və ya mühitə qoyulmuş modeli oxumaq |
adi let | görünüş qiyməti yalnız göstərir |
Bütün bunlar birlikdə MVVM üslubunu yaradır: Model — məlumat strukturları və xidmətlər (şəbəkə, verilənlər bazası); ViewModel — ekranın vəziyyətini və məntiqini saxlayan @Observable sinif (QuizModel); View — vəziyyəti göstərən və istifadəçinin hərəkətlərini ViewModel-in metodlarına ötürən SwiftUI strukturu. İnterfeys yalnız əsas axında yenilənməli olduğu üçün ViewModel-ləri adətən @MainActor ilə işarələyirlər.
- 1Model faylı yarat
Cmd+Nbas,iOSbölməsindəSwift Fileseç, adınıQuizModelqoy vəCreatebas. Oraya@Observablesinfini yaz. - 2Görünüş faylı yarat
Yenə
Cmd+N, bu dəfəSwiftUI Viewşablonu; adıQuizView. Şablon#Previewblokunu da özü əlavə edir. - 3Kətanda yoxla
Önizləmədə düymələrə bas və sualın nömrəsinin, sonda isə nəticənin dəyişdiyini yoxla — simulyatoru işə salmağa ehtiyac yoxdur.
Əsas fikirlər
- Hər məlumatın bir sahibi olmalıdır — vahid həqiqət mənbəyi.
@State private vargörünüşün öz vəziyyətidir; dəyişəndəbodyyenidən hesablanır.@Bindingvalideynin qiymətinə iki tərəfli bağlantıdır və$ilə ötürülür.@Observablesinif (iOS 17+) oxunan xassələri özü izləyir; modeli@Stateilə saxla,@Environmentvə@Bindableilə paylaş.- MVVM: Model məlumat verir,
@ObservableViewModel vəziyyəti idarə edir, View onu göstərir.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.