- Published on
Repository patterni
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
10.2 darsda biznes logikasini viewdan view modelga ko'chirdingiz. Endi keyingi qavatga tushamiz: ma'lumot qayerdan keladi?
Hozir view model tarmoq so'rovlari yoki ma'lumot bazasiga bevosita murojaat qilishi mumkin. Bu yana ikkita muammo yaratadi: view model ikki turli ish qilyapti va Preview uchun real tarmoq kerak.
Repository patterni bu ikkala muammoni hal qiladi.
Kutubxonachi metafori: kitob so'raysiz β olasiz. Kutubxonachidan kitob javondan olindimi, boshqa kutubxonadan buyurtma berilganmi yoki raqamli arxivdan olindimi β bilmaysiz. Shunchaki so'radingiz va oldingiz. Repository xuddi shunday ishlaydi.
To'rt qadam
// 1-qadam: Protokol β view model faqat shu bilan gaplashadi
protocol KitobRepository {
func kitoblarniYukla() async throws -> [Kitob]
func saqlash(_ kitob: Kitob) async throws
}
// 2-qadam: Haqiqiy implementatsiya β tarmoqdan ma'lumot oladi
struct TarmoqKitobRepository: KitobRepository {
func kitoblarniYukla() async throws -> [Kitob] {
let url = URL(string: "https://api.example.com/kitoblar")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode([Kitob].self, from: data)
}
func saqlash(_ kitob: Kitob) async throws {
// API ga POST
}
}
// 3-qadam: Mock implementatsiya β testlar va Preview uchun
struct MockKitobRepository: KitobRepository {
func kitoblarniYukla() async throws -> [Kitob] {
// Darhol, bashoratli ma'lumot β tarmoq kerak emas
[Kitob(sarlavha: "Swift dasturlash"), Kitob(sarlavha: "Dizayn patternlari")]
}
func saqlash(_ kitob: Kitob) async throws {
// Hech narsa β bu soxta
}
}
// 4-qadam: View modeli β protokolga bog'liq, aniq turga emas
@Observable
class KitobKorinishiModeli {
var kitoblar: [Kitob] = []
var yuklanmoqda = false
// any kalit so'zi β KitobRepository ga mos istalgan turni saqlaydi
private let repository: any KitobRepository
// Produksiyada standart haqiqiy, testda mock uzating β bu dependency injection
init(repository: any KitobRepository = TarmoqKitobRepository()) {
self.repository = repository
}
func kitoblarniYukla() async {
yuklanmoqda = true
do {
kitoblar = try await repository.kitoblarniYukla()
} catch {
// Xatoni bu yerda boshqaring
}
yuklanmoqda = false
}
}
| Qator | Vazifasi |
|---|---|
protocol KitobRepository | Interfeys β shartnoma. View modeli faqat shu haqida biladi. |
struct TarmoqKitobRepository: KitobRepository | Haqiqiy implementatsiya β real tarmoq so'rovlari qiladi. |
struct MockKitobRepository: KitobRepository | Test va Preview implementatsiyasi β darhol, hardcoded ma'lumot qaytaradi. |
private let repository: any KitobRepository | any β KitobRepository ga mos istalgan turni saqlaydi. View modeli qaysi biri muhim emas. |
init(repository: any KitobRepository = TarmoqKitobRepository()) | Produksiyada hech narsa uzatmang. Test uchun mock uzating. |
Repository variantlari
// Lokal saqlash repository β xuddi shu pattern, boshqa ma'lumot manbasi
struct LocalKitobRepository: KitobRepository {
let modelContext: ModelContext
func kitoblarniYukla() async throws -> [Kitob] {
let tavsif = FetchDescriptor<Kitob>()
return try modelContext.fetch(tavsif)
}
func saqlash(_ kitob: Kitob) async throws {
modelContext.insert(kitob)
try modelContext.save()
}
}
// View modeli o'zgarmaydi β faqat repository o'zgaradi
// Preview da mock inject qilish
#Preview {
// Mock β tarmoq yo'q, kutish yo'q, bashoratli ma'lumot
let model = KitobKorinishiModeli(repository: MockKitobRepository())
KitobRo'yxatiKorinishi(model: model)
}
// Xato holatini test qilish β haqiqiy muvaffaqiyatsiz server kerak emas
struct MuvaffaqiyatsizKitobRepository: KitobRepository {
func kitoblarniYukla() async throws -> [Kitob] {
throw URLError(.notConnectedToInternet)
}
func saqlash(_ kitob: Kitob) async throws { }
}
#Preview("Xato holati") {
KitobRo'yxatiKorinishi(model: KitobKorinishiModeli(repository: MuvaffaqiyatsizKitobRepository()))
}
Tezkor ma'lumotnoma
| Sintaksis | Vazifasi |
|---|---|
protocol Repo { func yukla() async throws -> [T] } | Repository interfeysi β barcha implementatsiyalar bajarishi kerak |
struct HaqiqiyRepo: Repo { } | Produksiya implementatsiyasi β haqiqiy ma'lumot manbasiga gaplashadi |
struct MockRepo: Repo { } | Test/Preview implementatsiyasi β tezkor, hardcoded ma'lumot |
private let repo: any Repo | Protokolga mos istalgan turni saqlaydi |
init(repo: any Repo = HaqiqiyRepo()) | Produksiyada standart β test uchun mock uzating |
π― Topshiriq: repository qo'shish
10.2 darsdan VazifaKorinishiModeli ni oling. Hozir u vazifalar massivini to'g'ridan-to'g'ri saqlaydi. VazifaRepository protokolini vazifalarniYukla() va vazifaQoshish(_ matn: String) metodlari bilan yarating. LocalVazifaRepository β xotira massivi bilan va MockVazifaRepository β uchta hardcoded vazifa bilan yozing. View modelini any VazifaRepository ga bog'lang. Preview Mock bilan ishlashini tasdiqlang.