- Published on
SwiftUI Map App β ViewModel: @StateObject va @EnvironmentObject
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
ViewModel: @StateObject va @EnvironmentObject
Bu videoda MVVM arxitekturasining markaziy qismi β LocationsViewModel quriladi va barcha view-larga @EnvironmentObject orqali uzatiladi.
LocationsView yaratish
Views/ papkasida yangi SwiftUI View fayli yaratiladi β LocationsView.swift. Bu ilovaning asosiy ekrani bo'ladi.
LocationsViewModel β boshlang'ich versiya
Avval ViewModel-ni xuddi shu faylda qurib ko'ramiz, keyin alohida faylga ko'chiramiz.
import Foundation
import MapKit
class LocationsViewModel: ObservableObject {
@Published var locations: [Location] = []
init() {
let locations = LocationsDataService.locations
self.locations = locations
}
}
Va LocationsView-da:
struct LocationsView: View {
@StateObject private var vm = LocationsViewModel()
var body: some View {
List {
ForEach(vm.locations) { location in
Text(location.name)
}
}
}
}
Bu boshlang'ich versiya β @StateObject bilan faqat shu view ichida ishlatiladi. Keyinroq @EnvironmentObject-ga o'tkaziladi.
Location-ni Identifiable-ga moslashtirish
ForEach bilan ishlaganda Swift har bir elementni farqlash uchun noyob identifikator talab qiladi. Buning uchun Location struct-i Identifiable protokoliga mos bo'lishi kerak:
// β Tez, lekin noto'g'ri
let id: String = UUID().uuidString
// Har safar yaratilganda yangi id hosil bo'ladi β
// ikkita bir xil Location turli id-ga ega bo'ladi
To'g'ri yondashuv β id-ni mavjud ma'lumotlardan hisoblash:
// β
To'g'ri
struct Location: Identifiable {
let name: String
let cityName: String
// ... boshqa maydonlar
var id: String {
name + cityName
}
}
Nima uchun name + cityName?
- Bir shahardan ikki xil joy β nomlar farq qiladi β id farq qiladi β
- Ikki shahardagi bir xil nomli joy β shahar nomi farq qiladi β id farq qiladi β
- To'liq bir xil joy β id ham bir xil β Swift ularni bir ob'ekt deb biladi β
Haqiqiy ilovada bu id odatda backend ma'lumotlar bazasidagi unikal identifikator bo'ladi. Bu misolda ma'lumotlar bazasi yo'qligi uchun name + cityName kombinatsiyasi ishlatiladi.
@EnvironmentObject β ViewModel-ni butun ilovaga tarqatish
@StateObject bilan ViewModel faqat bitta view-da mavjud. Boshqa view-larga @Binding orqali uzatish kerak bo'ladi β bu katta loyihalarda chalkash bo'lib ketadi.
Yechim: ViewModel-ni ilova darajasida yaratib, @EnvironmentObject orqali barcha child view-larga tarqatish.
App.swift β ViewModel-ni muhitga qo'shish
@main
struct SwiftUIMapAppApp: App {
@StateObject private var vm = LocationsViewModel()
var body: some Scene {
WindowGroup {
LocationsView()
.environmentObject(vm)
}
}
}
LocationsView β muhitdan olish
struct LocationsView: View {
@EnvironmentObject private var vm: LocationsViewModel
var body: some View {
List {
ForEach(vm.locations) { location in
Text(location.name)
}
}
}
}
Endi vm β yangi yaratilmaydi, muhitdan (environment) olinadi.
Preview uchun
Preview muhitda @EnvironmentObject mavjud bo'lmaydi β shuning uchun preview-ga alohida qo'shish kerak:
struct LocationsView_Previews: PreviewProvider {
static var previews: some View {
LocationsView()
.environmentObject(LocationsViewModel())
}
}
ViewModel-ni alohida faylga ko'chirish
LocationsViewModel kodi ViewModels/ papkasidagi yangi Swift File β LocationsViewModel.swift-ga ko'chiriladi:
import Foundation
import MapKit
class LocationsViewModel: ObservableObject {
@Published var locations: [Location] = []
init() {
self.locations = LocationsDataService.locations
}
}
@StateObject va @EnvironmentObject β taqqoslash
@StateObject | @EnvironmentObject | |
|---|---|---|
| Yaratilish joyi | Shu view ichida | App yoki ota view-da |
| Kirish imkoni | Faqat shu view | Barcha child view-lar |
| Uzatish usuli | @Binding kerak | Avtomatik, muhit orqali |
| Qachon ishlatiladi | Lokal holat | Global, umumiy holat |
Video oxiridagi loyiha holati
SwiftUIMapApp/
βββ Models/
β βββ Location.swift β Identifiable qo'shildi
βββ Views/
β βββ LocationsView.swift β @EnvironmentObject ishlatadi
βββ ViewModels/
β βββ LocationsViewModel.swift β yangi fayl
βββ DataServices/
β βββ LocationsDataService.swift
βββ SwiftUIMapAppApp.swift β vm yaratiladi va muhitga uzatiladi
Ilovani build qilib LocationsView-da barcha joy nomlari ko'rinishi kerak β bu ViewModel to'g'ri ulanganligi belgisi.
Keyingi videoda LocationsView-ning asosiy UI qismi quriladi β xarita, pinlar va joy kartasi.