- Published on
SwiftUI da dependency injection
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Repository patterningiz tayyor β lekin endi savol: view model repositoryni qayerdan oladi?
Dependency injection β turga uning kerakli narsalarini u o'zi yaratish o'rniga tashqaridan berish. Bu tushuncha oddiy, ammo u nima imkon beradi:
- Ma'lumot manbasini bir joyda almashtirish
- Preview va testlar uchun mock inject qilish
- View modeli va repository bir-biridan mustaqil bo'lish
Constructor injection β eng oddiy usul
@Observable
class KitobKorinishiModeli {
private let repository: any KitobRepository
// Constructor injection β dependency yaratilish vaqtida uzatiladi
// init() parametri orqali β oddiy va aniq
init(repository: any KitobRepository = TarmoqKitobRepository()) {
self.repository = repository
}
}
// Produksiyada β hech narsa uzatmang, standart ishlatiladi
let model = KitobKorinishiModeli()
// Test yoki Preview da β mock uzating
let testModel = KitobKorinishiModeli(repository: MockKitobRepository())
Environment injection β keng miqyosli usul
Ko'p ko'rinish bitta repositoryga muhtoj bo'lsa, har birining konstruktoriga uzatish charchashga olib keladi. Environment injection bir marta inject qilish imkonini beradi.
// 1-qadam: Environment kalitini ro'yxatdan o'tkazish
struct KitobRepositoryKaliti: EnvironmentKey {
// Ko'rinish environment da qiymat topilmasa shu standart ishlatiladi
static let defaultValue: any KitobRepository = TarmoqKitobRepository()
}
// 2-qadam: EnvironmentValues ga nomlangan accessor qo'shish
extension EnvironmentValues {
var kitobRepository: any KitobRepository {
get { self[KitobRepositoryKaliti.self] }
set { self[KitobRepositoryKaliti.self] = newValue }
}
}
// 3-qadam: Ilova yoki sahna darajasida inject qilish
@main
struct MeningIlovam: App {
var body: some Scene {
WindowGroup {
ContentView()
// Bu qatorni o'zgartirish β butun ilovaning ma'lumot manbasini almashtiradi
.environment(\.kitobRepository, TarmoqKitobRepository())
}
}
}
// 4-qadam: Ierarxiyadagi istalgan joyda o'qish
struct KitobRo'yxatiKorinishi: View {
@Environment(\.kitobRepository) var repository
@State private var model: KitobKorinishiModeli?
var body: some View {
Text("Kitoblar ro'yxati")
.onAppear {
model = KitobKorinishiModeli(repository: repository)
}
}
}
| Qator | Vazifasi |
|---|---|
struct KitobRepositoryKaliti: EnvironmentKey | SwiftUI environment tizimida yangi kalit ro'yxatdan o'tkazadi. defaultValue β hech kim inject qilmasa ishlatiladi. |
extension EnvironmentValues | \.kitobRepository kabi nomlangan accessor qo'shadi. |
.environment(\.kitobRepository, TarmoqKitobRepository()) | Bu nuqtadan pastdagi barcha viewlarga dependency inject qiladi. |
@Environment(\.kitobRepository) var repository | Ko'rinishga environment dan dependency o'qiydi. |
@Observable ob'ektlarni inject qilish β yanada oddiy
@Observable
class IlovaSozlamalari {
var qorongRejimda = false
}
// Ilova kirish nuqtasida inject qilish β kalit kerak emas
ContentView()
.environment(IlovaSozlamalari())
// Istalgan viewda o'qish β tur bilan
@Environment(IlovaSozlamalari.self) var sozlamalar
Preview da mock
#Preview {
KitobRo'yxatiKorinishi()
// Bitta modifier barcha pastdagi viewlarga mock beradi
.environment(\.kitobRepository, MockKitobRepository())
}
Qaysi usulni tanlash
// Constructor injection β oddiy va aniq
// Foydalaning: view model va bitta yoki ikki ko'rinish uchun
init(repository: any KitobRepository = TarmoqKitobRepository()) {
self.repository = repository
}
// Environment injection β keng miqyosli
// Foydalaning: ko'p viewda kerak, har biriga uzatmaslik uchun
.environment(\.kitobRepository, TarmoqKitobRepository())
Qoida: Constructor injection bilan boshlang β oddiy va aniq. Ko'p ko'rinishga kerakli dependency bo'lsa environment ga o'ting.
Tezkor ma'lumotnoma
| Sintaksis | Vazifasi |
|---|---|
init(dep: any Protocol = HaqiqiyImpl()) | Constructor injection standart bilan |
struct Kalit: EnvironmentKey { ... } | Environment da yangi dependency ro'yxatdan o'tkazadi |
extension EnvironmentValues { var dep } | Nomlangan accessor β \.depNomi yozish imkoni |
.environment(\.depNomi, implementatsiya) | Ierarxiyadagi barcha pastki viewlarga inject qiladi |
@Environment(\.depNomi) var dep | Ko'rinishdan environment da o'qiydi |
.environment(MeningObservable()) | @Observable ob'ektni tur bilan inject qiladi β kalit shart emas |
π― Topshiriq: environment injection
10.3 darsdan VazifaRepository ni oling. Constructor injection ishlatayotgan bo'lsangiz β environment injection ga o'tkazib ko'ring. VazifaRepositoryKaliti va EnvironmentValues extension yozing. MyApp da LocalVazifaRepository inject qiling. Preview da MockVazifaRepository inject qiling. Ikkala holatda ham to'g'ri ma'lumot ko'rinishini tasdiqlang.