Combine — asosiy tushunchalar, Publisher va reaktiv dasturlash

Muallif: IT Sectr Nashr etilgan: 2026-05-03 O'qish vaqti: 11 daq

Combine — bu Apple tomonidan iOS 13, macOS Catalina, tvOS 13 va watchOS 6 da taqdim etilgan mahalliy reaktiv dasturlash freymvorkidir. U Publisher va Subscriber namunasi orqali asinxron hodisalarni qayta ishlash uchun deklarativ Swift API ni taqdim etadi, delegatlar, yopilishlar va NotificationCenter ni yagona zanjir bilan almashtiradi. Apple, 2025 ma'lumotlariga ko'ra, Combine SwiftUI va zamonaviy iOS arxitekturalari uchun asos bo'lib, async/await va Structured Concurrency bilan chambarchas bog'liq holda ishlaydi. Freymvork ip xavfsizligi kafolatlari bilan asinxron operatsiyalarni kompozitsiya qilish uchun mo'ljallangan.

Asosiy fikrlar

  • Combine — Publisher, Subscriber, Subject turlari va Failure orqali xato turlari bilan Apple-ning mahalliy reaktiv freymvorki
  • Publisher vaqt davomida hodisalarni chiqaradi: Output qiymatlari, muvaffaqiyat yoki Failure xatosi bilan tugashi mumkin
  • Subscriber Publisher dan hodisalarni oladi va Demand orqali ma'lum miqdordagi elementlarni so'rashi mumkin
  • Operatorlar map, flatMap, filter, combineLatest, zip, debounce poyga holatisiz oqimlarni o'zgartiradi
  • SwiftUI interfeysni reaktiv yangilash uchun @Published, ObservableObject va @StateObject orqali Combine dan foydalanadi

Combine nima?

Combine — bu Apple SDK ga o'rnatilgan deklarativ reaktiv dasturlash freymvorkidir. U Reactive Streams namunasini amalga oshiradi: Publisher qiymatlarni ishlab chiqaradi, Subscriber ularni iste'mol qiladi va operatorlar oqimni ular o'rtasida o'zgartiradi. Combine callback va delegat muammosini hal qiladi, tarmoq javoblaridan UI o'zgarishlarigacha bo'lgan har qanday asinxron hodisalar uchun yagona kompozitsiya modelini taqdim etadi.

Combine paydo bo'lishidan oldin iOS dasturchilari uchinchi tomon kutubxonalaridan, birinchi navbatda RxSwift dan foydalanganlar. Apple Combine ni ekotizimga chuqur integratsiya bilan mahalliy muqobil sifatida yaratdi: freymvork @objc ko'priklari orqali Objective-C ni qo'llab-quvvatlaydi, KVO (NSObject.keyValuePublisher orqali Key-Value Observing) va NotificationCenter bilan ishlaydi, shuningdek SwiftUI uchun asosdir. SwiftUI da nashr etilgan barcha UIKit komponentlari ko'rinishlarni yangilash uchun Combine dan foydalanadi.

Combine Swift Concurrency ni hisobga olgan holda ishlab chiqilgan: iOS 15 dan boshlab Publisher .values orqali AsyncSequence ga aylantirilishi va for-await-in sikllarida ishlatilishi mumkin. Async funksiyalarining Publisher ga teskari aylantirilishi Future orqali amalga oshiriladi. Apple WWDC 2024 ma'lumotlariga ko'ra, Combine yagona asinxron chaqiruvlar uchun async/await paydo bo'lishiga qaramay, UIKit ilovalarida oqim ma'lumotlarini qayta ishlash uchun tavsiya etilgan freymvork bo'lib qolmoqda.

Combine ning asosiy tushunchalari

Combine uch protokolga asoslanadi: Publisher (Output tipidagi qiymatlarni chiqaradi, Failure tipidagi xato bilan tugashi mumkin), Subscriber (qiymatlarni oladi, Demand ni boshqaradi — so'ralgan elementlar soni), Subscription (bekor qilish imkoniyati bilan Publisher-Subscriber aloqasini ifodalaydi). Ma'lumot uzatish kanali subscribe da ishga tushiriladi va cancel, completion yoki error da tugaydi. Demand — Combine ning noyob kontseptsiyasi: Subscriber Publisher ga nechta elementni qayta ishlashga tayyorligini bildiradi, protokol darajasida backpressure ni amalga oshiradi.

Publisher va Subscriber: reaktiv oqim arxitekturasi

Publisher — ikkita bog'liq turga ega protokol: Output (chiqarilgan qiymatlar turi) va Failure (Error ni amalga oshiradigan xato turi). Agar oqim xato bilan tugamasa, Failure Never sifatida ko'rsatiladi — bu Subscriber ga onReceive faqat Output bilan chaqirilishini kafolatlaydi. O'rnatilgan Publisher larga Just (bitta qiymat), Sequence (massiv), URLSession.DataTaskPublisher (tarmoq so'rovi), NotificationCenter.Publisher va @Published property wrapper kiradi.

swift
import Combine

// Ketma-ketlikdan Publisher yaratish
let publisher = [1, 2, 3, 4, 5].publisher

// Qiymatlarni qayta ishlash bilan Subscriber yaratish
class PrintSubscriber: Subscriber {
    typealias Input = Int
    typealias Failure = Never

    func receive(subscription: Subscription) {
        subscription.request(.unlimited)
    }

    func receive(_ input: Int) -> Subscribers.Demand {
        print("Received: \(input)")
        return .unlimited
    }

    func receive(completion: Subscribers.Completion<Never>) {
        print("Tugallandi")
    }
}

publisher.subscribe(PrintSubscriber())

Subscription va Demand

Subscription — bu Publisher va Subscriber o'rtasidagi faol aloqani ifodalovchi protokol. Subscriber Subscription ni receive(subscription:) metodida oladi va Demand ni ko'rsatish uchun request(_:) ni chaqiradi: .unlimited (barcha qiymatlar), .max(N) (cheklangan son) yoki .none (pauza). Demand dinamik o'zgarishi mumkin — Subscriber ma'lumot olish jarayonida so'ralgan elementlar sonini oshirishi yoki kamaytirishi mumkin. Bu Publisher tomonda buferlashsiz backpressure ni ta'minlaydi.

Subject va CurrentValueSubject

Subject — bu Publisher va Subscriber ni birlashtiruvchi turdir. Subject Publisher sifatida (unga obuna bo'lish mumkin) va bir vaqtning o'zida Subscriber sifatida (unga qiymatlar yuborish mumkin) ishlatilishi mumkin. Combine ikki turdagi Subject ni taqdim etadi: PassthroughSubject (holatni saqlamaydi, faqat yangi qiymatlarni uzatadi) va CurrentValueSubject (joriy qiymatni saqlaydi va uni yangi obunachilarga uzatadi). Subject imperativ kodni reaktiv Combine zanjirlariga integratsiya qilish uchun zarur.

swift
let subject = PassthroughSubject<String, Never>()

// Publisher sifatida obuna
let cancellable = subject
    .map { $0.uppercased() }
    .sink { print($0) }

// Subscriber sifatida qiymatlarni yuborish
subject.send("hello")  // "HELLO" chop etadi
subject.send("dunyo")  // "WORLD" chop etadi

CurrentValueSubject PassthroughSubject dan boshlang'ich qiymat va value xususiyatining mavjudligi bilan farq qiladi: obunachi obuna bo'lganda darhol joriy qiymatni, keyin esa barcha keyingi yangilanishlarni oladi. CurrentValueSubject.value o'qish va yozish uchun mavjud — value ning o'zgarishi avtomatik ravishda barcha obunachilarga yangi qiymatni yuboradi. Bu CurrentValueSubject ni MVVM arxitekturasida holatni ifodalash uchun ideal tanlovga aylantiradi: ViewModel CurrentValueSubject ni nashr etadi, View o'zgarishlar bilan sink orqali obuna bo'ladi.

Ikkala Subject ham oqimni send(completion: .finished) yoki send(completion: .failure(error)) chaqiruvi bilan tugatishga imkon beradi. Tugatilgandan so'ng, Subject hodisalarni qabul qilish va uzatishni to'xtatadi. Tugamasligi kerak bo'lgan uzoq muddatli oqimlar (masalan, UI hodisalari) uchun tasodifiy send(completion:) chaqiruvini istisno qilish uchun Never Failure bilan PassthroughSubject dan foydalanish tavsiya etiladi.

O'zgartirish va birlashtirish operatorlari

Operatorlar Combine — yangi Publisher qaytaradigan Publisher metodlaridir. Har bir operator yuqori oqim Publisher ga obuna bo'ladigan va o'zgartirilgan qiymatlarni quyi oqimga chiqaradigan yangi ob'ekt yaratadi. Publisher generic tur bo'lgani uchun operatorlar qat'iy tipizatsiyani saqlaydi: map Output<A> ni Output<B> ga o'zgartiradi, tryMap xato ehtimolini qo'shadi. Combine taxminan 100 ta o'rnatilgan operatordan iborat.

KategoriyaOperatorMaqsad
O'zgartirishmap / tryMap / flatMapQiymatlar yoki oqimlarni o'zgartirish
Filtrlashfilter / compactMap / removeDuplicatesQiymatlarni tanlash yoki tozalash
BirlashtirishcombineLatest / zip / mergeBir nechta Publisher larni birlashtirish
Vaqt boshqaruvidebounce / throttle / delayHodisalarni kechiktirish va siyraklash
Xato boshqaruvicatch / retry / replaceErrorFailure dan keyin tiklanish
Demand boshqaruvibuffer / collectGuruhlash yoki buferlash

flatMap Combine da RxSwift versiyasidan muhim farqga ega: bir xil Failure turiga ega Publisher qaytaradigan closure ni qabul qiladi va ichki Publisher ni asosiy oqimga ochadi. maxPublishers: .max(1) bilan flatMap switchMap kabi harakat qiladi — yangi qiymat kelganda oldingi ichki Publisher ni bekor qiladi. Bu qidiruv stsenariylari uchun juda muhim: yangi belgi kiritilganda oldingi HTTP so'rovi avtomatik ravishda bekor qilinadi.

swift
// Oldingi so'rovni bekor qilish bilan debounce qidiruv
searchTextField.textPublisher
    .debounce(for: .seconds(0.3), scheduler: RunLoop.main)
    .removeDuplicates()
    .flatMap(maxPublishers: .max(1)) { query in
        apiService.searchPublisher(query)
            .catch { _ in Just([]) }
    }
    .receive(on: DispatchQueue.main)
    .sink { results in
        self.tableView.reloadData()
    }
    .store(in: &cancellables)

Birlashtirish operatorlari — combineLatest va zip — RxSwift dagi kabi ishlaydi: combineLatest har qanday Publisher o'zgarganda barcha Publisher larning oxirgi qiymatlari kortejini chiqaradi; zip qiymatlarni indeks bo'yicha juft-juft birlashtiradi. merge bir xil turdagi Publisher larni bitta oqimga birlashtiradi, preserveOrder kafolatlanmaydi. Combine da shuningdek select — bir nechtadan birinchi tugagan Publisher ni tanlaydigan noyob operator, va share — oqimni qayta bajarmasdan ko'plab obunachilarga multicast qiluvchi operator mavjud.

Schedulerlar va iplarni boshqarish

Scheduler Combine da — operatorlar uchun bajarish kontekstini belgilaydigan protokoldir. RxSwift ning 5+ o'rnatilgan Scheduler laridan farqli o'laroq, Combine mavjud Apple mexanizmlaridan foydalanadi: DispatchQueue, RunLoop va OperationQueue. Bu turlarning har biri Scheduler protokoliga mos keladi, bu ularni qo'shimcha adapterlarsiz to'g'ridan-to'g'ri receive(on:) va subscribe(on:) ga uzatish imkonini beradi.

receive(on:) quyi oqimni belgilangan Scheduler ga o'tkazadi — RxSwift dagi observeOn ning ekvivalenti. receive(on:) dan keyingi barcha operatorlar belgilangan Scheduler da bajariladi. subscribe(on:) yuqori oqimni o'tkazadi — Publisher ning bajarilishiga ta'sir qiladi. Odatiy namuna: fon ishi uchun subscribe(on: DispatchQueue.global()) va UI yangilash uchun receive(on: DispatchQueue.main). SwiftUI da .onReceive ishlatganda asosiy ipga o'rnatilgan bog'lanish talab qilinmaydi, lekin sink uchun aniq receive(on:).main tavsiya etiladi.

swift
// Fon yuklash + asosiy ipda UI
URLSession.shared.dataTaskPublisher(for: url)
    .subscribe(on: DispatchQueue.global(qos: .background))
    .tryMap { data, response -> Data in
        guard let http = response as? HTTPURLResponse,
              http.statusCode == 200 else {
            throw URLError(.badServerResponse)
        }
        return data
    }
    .receive(on: DispatchQueue.main)
    .decode(type: User.self, decoder: JSONDecoder())
    .sink(receiveCompletion: { print($0) },
         receiveValue: { self.nameLabel.text = $0.name })
    .store(in: &cancellables)

RunLoop.main — UI operatsiyalari uchun DispatchQueue.main ga alternativdir. Farq shundaki, RunLoop.main ilovaning joriy hodisa sikliga bog'langan, DispatchQueue.main esa asosiy ipning global navbatiga. UIKit uchun DispatchQueue.main, SwiftUI uchun RunLoop.main tavsiya etiladi. ImmediateWhenScheduler operatsiyalarni joriy ipda sinxron bajaradi — testlar va oddiy Publisher lar uchun sukut bo'yicha ishlatiladi.

Combine va SwiftUI: ObservableObject orqali integratsiya

ObservableObject — o'zgarishlarni nashr etadigan ob'ektlar uchun SwiftUI protokolidir. ObservableObject ni amalga oshiradigan sinf @Published property wrapper indan o'zgarishlari avtomatik ravishda SwiftUI ni qayta chizish zarurati haqida xabardor qiladigan xususiyatlar uchun foydalanishi mumkin. @Published ostida wrappedValue o'zgarganda objectWillChange Publisher ini xabardor qiladigan Publisher yaratadi. SwiftUI @StateObject, @ObservedObject yoki @EnvironmentObject orqali objectWillChange ga obuna bo'ladi.

@Published va @StateObject

@Published — Combine ni SwiftUI da integratsiya qilishning eng keng tarqalgan usuli. @Published xususiyatining qiymati o'zgarganda, SwiftUI ushbu ob'ektdan foydalanadigan barcha View larni yangilaydi. @StateObject ObservableObject namunasini yaratadi va uning o'zgarishlariga obuna bo'ladi. @StateObject bilan yaratilgan View @Published xususiyatlari o'zgarganda avtomatik ravishda qayta chiziladi. Agar ob'ekt bir nechta View lar o'rtasida uzatilishi kerak bo'lsa, @ObservedObject yoki @EnvironmentObject ishlatiladi.

swift
class UserViewModel: ObservableObject {
    @Published var name: String = ""
    @Published var age: Int = 0
    private var cancellables = Set<AnyCancellable>()

    init() {
        $name
            .debounce(for: .seconds(0.5), scheduler: RunLoop.main)
            .sink { [weak self] newName in
                AnalyticsService.logNameChange(newName)
            }
            .store(in: &cancellables)
    }
}

struct UserView: View {
    @StateObject var viewModel = UserViewModel()

    var body: some View {
        TextField("Name", text: $viewModel.name)
    }
}

AnyCancellable — Cancellable uchun tur tozalagich, obunani bekor qilish tokenini saqlaydi. Set<AnyCancellable> obunalarning hayot aylanishini boshqaradi: egasining deinitsializatsiyasida barcha Cancellable lar avtomatik ravishda bekor qilinadi. SwiftUI loyihalarida Set<AnyCancellable> ObservableObject sinfida e'lon qilinadi, obunalar esa .store(in: &cancellables) orqali qo'shiladi. UIKit uchun UIViewController da &cancellables orqali saqlash yoki qo'lda cancel() chaqiruvi bilan bir xil mexanizmlar qo'llaniladi.

Combine vs RxSwift

Combine va RxSwift bir xil reaktiv dasturlash vazifalarini hal qiladi, ammo fundamental arxitektura farqlariga ega. Combine — iOS 13 gacha orqaga moslik bilan Apple SDK ning bir qismi, RxSwift — iOS 8+ qo'llab-quvvatlashi bilan uchinchi tomon kutubxonasi. Combine Failure generic orqali qat'iy xato tipizatsiyasidan foydalanadi, RxSwift — yagona Error tipidan. Combine platforma darajasida SwiftUI bilan integratsiyalangan, RxSwift UI kengaytmalari uchun RxCocoa talab qiladi.

Combine va RxSwift o'rtasidagi tanlov loyiha talablariga bog'liq. Agar minimal iOS versiyasi >= 13 va loyiha SwiftUI dan foydalansa — Combine o'rnatilgan integratsiya va qo'shimcha bog'liqliklarning yo'qligi tufayli tabiiy tanlovdir. Agar loyiha iOS 11-12 ni qo'llab-quvvatlasa, mavjud RxSwift kod bazasiga ega bo'lsa yoki faqat RxSwift da mavjud bo'lgan maxsus operatorlarni talab qilsa (masalan, Observable.from(path:)), — RxSwift asosli yechim bo'lib qoladi.

XususiyatCombineRxSwift
YaratuvchiApple (SDK ga o'rnatilgan)ReactiveX (jamoa)
iOS versiyasiiOS 13+iOS 8+
Xato turiGeneric Failure (UI uchun Never)Error (har qanday)
UI integratsiyasi@Published + SwiftUIRxCocoa + UIKit
Operatorlar~100 o'rnatilgan400+ operator
Swift Concurrency.values orqali (async sequence)Ko'prik kutubxonasi orqali

Tez-tez beriladigan savollar

PassthroughSubject va CurrentValueSubject o'rtasidagi farq nima?

PassthroughSubject holatni saqlamaydi — obunachi faqat obunadan keyin yuborilgan hodisalarni oladi. CurrentValueSubject joriy qiymatni saqlaydi va uni har bir yangi obunachiga obuna bo'lganda darhol uzatadi. CurrentValueSubject holatni ifodalash uchun mos keladi (masalan, isLoggedIn).

Combine da obunani qanday bekor qilish mumkin?

Obuna AnyCancellable qaytaradi, u cancel() chaqirilganda yoki deinitsializatsiyada bekor qilinadi. Guruh boshqaruvi uchun Set<AnyCancellable> dan foydalaning — set tozalanganda barcha obunalar bekor qilinadi. Bu RxSwift dagi DisposeBag ning analogidir.

async/await dan keyin Combine ni o'rganish kerakmi?

Ha, Combine oqim ma'lumotlari uchun dolzarb bo'lib qolmoqda: UI hodisalari, debounce, combineLatest, WebSocket. async/await yagona so'rovlar uchun qulay, Combine — uzluksiz yoki bir nechta oqimlar uchun. Ikkala freymvork bir-birini to'ldiradi — Publisher AsyncSequence ga aylantirilishi mumkin.

Combine ni UIKit bilan qanday ishlatish mumkin?

UIKit o'rnatilgan Publisher larga ega emas, ammo Apple kengaytmalarni taqdim etadi: NotificationCenter.default.publisher(for:), Timer.publish, URLSession.dataTaskPublisher. Maxsus UI hodisalari uchun Future yoki Subject orqali Publisher ga o'ralgan PassthroughSubject yoki @IBAction ishlatiladi.

Combine da backpressure nima?

Backpressure — oqim tezligini boshqarish mexanizmi: Subscriber Demand orqali Publisher ga nechta elementni qayta ishlashga tayyorligini bildiradi. Agar Demand = .max(1) bo'lsa, Publisher keyingi qiymatni yuborishdan oldin so'rovni kutadi. Bu ishlab chiqaruvchi va iste'molchi tezliklari mos kelmasligida buferning to'lib ketishining oldini oladi.

Xulosa

  • Combine — Publisher-Subscriber namunasi va qat'iy xato tipizatsiyasi bilan iOS 13+ uchun Apple-ning mahalliy reaktiv freymvorki
  • Publisher va Subscriber backpressure uchun Demand boshqaruvi bilan aloqa kanalini tashkil qiladi
  • Subject (Passthrough va CurrentValue) imperativ kodni reaktiv zanjirlarga integratsiya qiladi
  • Operatorlar map, flatMap, combineLatest, debounce, catch oqimlarning deklarativ qayta ishlanishini ta'minlaydi
  • Schedulerlar DispatchQueue va RunLoop orqali UI ni bloklamasdan bajarish iplarini boshqaradi
  • SwiftUI reaktiv View lar uchun @Published, ObservableObject va @StateObject orqali Combine dan foydalanadi
  • RxSwift iOS 8+ loyihalari uchun muqobil bo'lib qoladi, Combine — iOS 13+ yangi loyihalar uchun tanlovdir

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing