- Published on
Combine: Publishers va Subscribers (Murakkab daraja)
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
1. @Published aslida qanday ishlaydi?
Biz shu paytgacha barcha ma'lumotlarni e'lon qilish uchun (publish) @Published dan foydalanib keldik:
class CombineViewModel: ObservableObject {
@Published var data: [String] = []
}
Biroq, bu asosan qulaylik (wrapper) hisoblanadi. Combine'da ikkita asosiy Publisher turi bor: CurrentValueSubject va PassthroughSubject.
CurrentValueSubject
CurrentValueSubject o'zida har doim joriy (oxirgi marta berilgan) qiymatni saqlab turadi. Demak u initsializatsiya paytida boshlang'ich qiymat (initial value) talab qiladi.
import Combine
class CombineDataService {
// String turidagi ma'lumot, boshlang'ich qiymati: "Boshlang'ich"
let currentValuePublisher = CurrentValueSubject<String, Never>("Boshlang'ich")
func publishData() {
// Yangi qiymat yuborish
currentValuePublisher.send("Yangi xabar 1")
}
}
PassthroughSubject
PassthroughSubject esa o'zida hech qanday qiymat saqlamaydi. U faqat kanal vazifasini o'taydi (ma'lumot undan o'tib ketadi). Agar unga kimdir obuna (subscribe) bo'lmagan bo'lsa, yuborilgan ma'lumot shunchaki yo'qoladi. U xotiradan joy tejash uchun zo'r vosita.
class CombineDataService {
// Boshlang'ich qiymat kiritilmaydi
let passthroughPublisher = PassthroughSubject<String, Error>()
func publishData() {
passthroughPublisher.send("O'tib ketuvchi xabar")
}
}
2. Publisher zanjirlarini (Pipelines) boshqarish
Biz passthroughPublisher orqali ketma-ket raqamlarni (1, 2, 3...) vaqt oralig'i bilan yuboryapmiz deylik. Qabul qiluvchi tomonda ularni qanday filtrlaymiz?
class CombineViewModel: ObservableObject {
@Published var data: [String] = []
var cancellables = Set<AnyCancellable>()
let dataService = CombineDataService()
init() {
addSubscribers()
}
func addSubscribers() {
dataService.passthroughPublisher
// 1. Zanjirdagi birinchi amal (Masalan, kelgan int ni string ga o'tkazish)
.map { String($0) }
// 2. Ketma-ketlik funksiyalari (Sequence Operations)
// .first() // Faqat birinchi ma'lumotni oladi va zanjirni to'xtatadi
// .first(where: { $0.count > 5 }) // Shartga mos kelgan birinchisini oladi
// tryFirst() yordamida agar kutilmagan qiymat kelsa, zanjirda Xato (Error) keltirib chiqarish mumkin
.tryFirst(where: { value in
if value == "3" {
throw URLError(.badServerResponse)
}
return value == "4"
})
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
break
case .failure(let error):
print("XATOLIK YUZ BERDI: \(error.localizedDescription)")
}
}, receiveValue: { [weak self] returnedValue in
self?.data.append(returnedValue)
})
.store(in: &cancellables)
}
}
Xulosa: SwiftUI da shunchaki array ni yangilash o'rniga, Combine zanjirlari orqali xabarlarni filtrlash, o'zgartirish, xatoliklarni boshqarish (.map, .first, .tryFirst) kabi amallarni bitta uzoq oqim (pipeline) doirasida mukammal boshqarishingiz mumkin.