Combine: mi ez, kulcsfogalmak és Publisher a Subscriberrel

Szerző: IT Sectr Megjelenés: 2026-03-17 Olvasási idő: 8 perc

A Combine egy reaktív programozási keretrendszer az Apple-től, amely az iOS 13-ban került bevezetésre. A Apple Documentation, 2025 szerint a Combine egységes deklaratív API-t biztosít aszinkron események feldolgozásához. A Publisher határozza meg az adatforrást, a Subscriber pedig feliratkozik azok fogadására.

Főbb pontok

  • Combine — beépített Apple keretrendszer reaktív programozáshoz, iOS 13-tól elérhető
  • Publisher — protokoll, amely meghatározza az Output értékek forrását a Failure hiba lehetőségével
  • Subscriber — protokoll, amely értékeket fogad a Publisher-től kezelt demand segítségével
  • Subject — Publisher, amely lehetővé teszi események kézi beszúrását (PassthroughSubject, CurrentValueSubject)
  • Operators — map, filter, combineLatest, flatMap folyamok transzformálásához és kombinálásához

Mi az a Combine?

Combine egy deklaratív Swift keretrendszer aszinkron események időbeli feldolgozásához. A callback-alapú megközelítésekkel ellentétben a Combine lehetővé teszi adatfeldolgozó csővezetékek leírását operátorok láncán keresztül. A keretrendszer integrálva van a Foundation (URLSession, Timer, NotificationCenter) és SwiftUI (ObservableObject, @Published) rendszerekkel.

Publisher protokoll

Minden Publisher protokollt implementáló típusnak meg kell határoznia az Output (értékek típusa) és Failure (hiba típusa) értékeket. A Publisher nem aktív a feliratkozásig — csak a subscribe meghívása után kezd eseményeket kibocsátani. Ez hideg szemantika, jellemző a reaktív folyamokra, amely növeli a hatékonyságot.

Subscriber protokoll

Subscriber három metóduson keresztül fogad eseményeket: receive(subscription:) — feliratkozás megerősítése demand kezeléssel; receive(_:) — új érték fogadása; receive(completion:) — folyam befejeződése sikerrel vagy hibával. A demand meghatározza, hogy a Subscriber hány értéket hajlandó fogadni — ez a backpressure mechanizmus.

Beépített Publisher-ek

Az Apple számos beépített Publisher-t biztosít: Just egy értéket bocsát ki és befejeződik, Future — aszinkron eredmény lezárással, Deferred — késleltetett Publisher létrehozás a feliratkozás pillanatáig. URLSession.dataTaskPublisher hálózati kérést alakít reaktív folyammá. Timer.publish periodikus időzítőt hoz létre. NotificationCenter.default.publisher értesítéseket alakít Publisher-ré. Ezek az integrációk lehetővé teszik az eseményekre való feliratkozást kézi híd nélkül.

Publisher és Subscriber a Combine-ban

A Combine-ban a Publisher és Subscriber a Subscription protokollon keresztül kapcsolódik. A Subscription egy összekötő objektum, amely vezérli az adatfolyamot. A fejlesztőnek nem kell saját Publisher típusokat létrehoznia — az Apple beépített Publisher-eket biztosít: Just, Future, Deferred, Fail, Empty, valamint Publisher-t URLSession és Timer számára.

Subject a Combine-ban

Subject egy Publisher, amelybe kézzel lehet értékeket küldeni. A PassthroughSubject nem tárol állapotot: az előfizető csak a feliratkozás után bekövetkezett eseményeket kapja. A CurrentValueSubject, hasonlóan az RxSwift BehaviorRelay-hoz, tárolja az aktuális értéket és azonnal továbbítja az új előfizetőnek.

Backpressure

A backpressure mechanizmus a Combine-ban szabályozza az adatátviteli sebességet. A Subscriber a subscription.request(.unlimited) vagy subscription.request(.max(N)) segítségével tájékoztatja a Publisher-t, hogy hány értéket képes feldolgozni. Ez megakadályozza a puffer túlcsordulását a termelő és fogyasztó egyenlőtlen sebessége esetén.

Combine operátorok

A Combine több mint 100 operátort tartalmaz kategóriákba sorolva: transzformáció (map, tryMap, flatMap), szűrés (filter, compactMap, removeDuplicates), kombinálás (combineLatest, merge, zip), időkezelés (debounce, throttle, delay) és hibakezelés (catch, replaceError, retry).

A combineLatest operátor két Publisher legutóbbi értékeit kombinálja — minden alkalommal, amikor bármelyikük új értéket bocsát ki, a lezárás mindkét frissített értékkel meghívódik. Ez az operátor nélkülözhetetlen űrlapok érvényesítésénél, ahol több beviteli mező állapotát kell egyidejűleg követni.

A debounce operátor késlelteti az értékek közzétételét, amíg egy meghatározott intervallum eltelik új események nélkül. Ez kritikus fontosságú keresőmezőknél: a kérés a szerverhez csak azután kerül elküldésre, miután a felhasználó 300-500 ms-ig abbahagyta a gépelést, ami 5-10-szeresére csökkenti a terhelést.

Hibakezelés

A Combine több hibakezelési stratégiát kínál operátor szinten. A catch elkapja a Failure-t és lecseréli a Publisher-t egy tartalékra — a folyam összeomlás nélkül folytatódik. A replaceError(with:) alapértelmezett értéket helyez a hiba helyére. A retry(_:) meghatározott számú alkalommal ismétli a feliratkozást hiba esetén. Fontos: a Never hibattípus a Publisher aláírásában garantálja, hogy a folyam soha nem végződik hibával — ez lehetővé teszi a Publisher használatát SwiftUI-ban Failure kezelés nélkül.

Combine kódpéldák

Az első példa az alapvető munkát mutatja Just — Publisher, amely egy értéket bocsát ki és befejeződik:

swift
let publisher = Just("Hello Combine")

publisher
    .sink(receiveCompletion: { completion in
        print("Befejezve: \(completion)")
    }, receiveValue: { value in
        print("Megkapva: \(value)")
    })

A második példa a Combine URLSession integrációját mutatja be hálózati kéréshez az eredmény fő szálon történő feldolgozásával:

swift
let url = URL(string: "https://api.example.com")!

URLSession.shared
    .dataTaskPublisher(for: url)
    .map { $0.data }
    .receive(on: DispatchQueue.main)
    .sink(receiveCompletion: { completion in
        if case .failure(let error) = completion {
            print("Hiba: \(error)")
        }
    }, receiveValue: { data in
        print("Adatok megkapva: \(data.count)")
    })

A harmadik példa — a CurrentValueSubject használata állapotkezeléshez:

swift
let counter = CurrentValueSubject<Int, Never>(0)

counter
    .sink { value in
        print("Számláló: \(value)")
    }

counter.send(1) // Megjeleníti: Számláló: 1
counter.send(2) // Megjeleníti: Számláló: 2
print(counter.value) // Megjeleníti: 2

Combine vs RxSwift

A Combine és az RxSwift ugyanazt a feladatot oldja meg — reaktív programozás, de eltérő megközelítésekkel. A Combine egy natív Apple keretrendszer, amely beépül a rendszerbe: nem igényel függőségek telepítését, integrált a SwiftUI-val és Foundation-nel. Az RxSwift egy harmadik féltől származó könyvtár iOS 9+ támogatással és szélesebb operátorkészlettel.

A Combine teljesítménye magasabb tipikus forgatókönyvekben a natív C implementációnak köszönhetően. Az RxSwift több hibakereső eszközt kínál (RxSwift.Resources.total, Debug), de objektumorientált architektúrája kevésbé hatékony lehet nagy adatfolyamokon. A választás közöttük kompromisszum a képességek és az integráció között.

Fontos különbség — a backpressure modell. A Combine-ban a Subscriber a Subscription segítségével kezeli a demand-ot, ami explicit kontrollt ad a folyam sebessége felett. Az RxSwift-ben a backpressure alapértelmezetten nem szabályozott — az Observable minden értéket kibocsát, a Subscriber pedig feldolgozza azokat érkezéskor. Nagy adatfolyamok esetén a Combine kiszámíthatóbb és memóriabiztosabb.

A Combine mélyen integrált a SwiftUI-val nyelvi szinten. A @Published Publisher-t generál, az ObservableObject objectWillChange Publisher-t biztosít. A SwiftUI View automatikusan feliratkozik ezekre a Publisher-ekre és újrarajzolódik változásokkor. Az UIKit-hez vannak külső burkolók, mint a CombineCocoa, de a Combine eredetileg SwiftUI-hoz lett tervezve, így UIKit integrációja további kódot igényel. Az RxSwift ezzel szemben gazdag ökoszisztémával rendelkezik UIKit-hez: az RxCocoa reaktív burkolókat biztosít az összes UI elemhez.

A Combine támogatja a Core Data integrációt NSFetchedResultsController Publisher segítségével. A Publisher új adatokat bocsát ki a Core Data verem minden változásakor: rekordok hozzáadása, törlése, frissítése. Ez lehetővé teszi reaktív listák építését kézi reloadData hívás nélkül. A Combine kombinálásával a NotificationCenter Publisher-rel UIApplication.willResignActiveNotification eseményhez, a fejlesztő reaktív réteget hoz létre a teljes alkalmazás életciklusához delegáltak és callback-ek nélkül. ObservableObject osztályok esetén a SwiftUI automatikusan frissíti a View-t a @Published tulajdonságok változásakor — a Combine biztosítja a teljes kapcsolatot egyetlen kézzel írt kódsor nélkül. A Combine kód moduláris tesztelése XCTestExpectation és Publisher.sink segítségével történik tesztesetekben Scheduler izolációval ImmediateScheduler-en keresztül.

UIKit projektekben Combine-nal dolgozva a fejlesztők gyakran használnak feliratkozást sink segítségével és tárolják az AnyCancellable-t Set-ben. Tipikus minta: a ViewController létrehoz egy nézetet, tárolja a cancellables-t, feliratkozik a Publisher-re a ViewModel-ből. A deinit során az összes feliratkozás automatikusan törlődik a Cancellables gyűjteményen keresztül. A Combine-ban az UICorrectel való helyes munkához UIControl.Event Publisher használható a publisher(for:) kiterjesztésen keresztül.

A Combine hibakeresése a print() vagy handleEvents() operátoron keresztül történik. A print(String) naplózza az összes eseményt: receive subscription, request demand, receive value, receive completion. A handleEvents finomabb kontrollt ad: lezárások adhatók meg a Publisher életciklusának minden szakaszához. A Combine teszteléséhez létezik a CombineExpectations — egy könyvtár, amely lehetővé teszi annak ellenőrzését, hogy a Publisher a várt értékeket bocsátja-e ki tesztekben virtuális idővel és demand kontrollal.

Combine a gyakorlatban

A Combine aktívan használatos a SwiftUI-ban űrlapkezeléshez: minden @Published tulajdonság Publisher-t generál, a SwiftUI feliratkozik rá a View.body-n keresztül. Több Publisher kombinálásával a combineLatest segítségével az űrlap érvényesítése deklaratívvá válik: minden Publisher egy mezőt követ, a combineLatest összegyűjti az összes értéket, a map ellenőrzi azokat és visszaadja a Submit gomb állapotát. A Publishers.Merge több azonos típusú Publisher-t egyesít eggyé — hasznos események gyűjtéséhez különböző vezérlőkről egyetlen folyamba.

A Combine UIKit integrációjához használja a UIControl Publisher kiterjesztésen keresztül: a button.publisher(for: .touchUpInside) visszaad egy Publisher-t, amely eseményt bocsát ki megnyomáskor. A CombineCocoa — egy közösségi könyvtár, amely Publisher-t biztosít az összes UIControl eseményhez, UITextView.text, UIScrollView.contentOffset. A feliratkozás lemondásakor a cancellables Store a deinit-ben tisztul, garantálva, hogy egyetlen feliratkozás sem éli túl a tulajdonosát. Több állapotú UIControl esetén használja a Publishers.MergeMany-t a Publisher-ek tömbben történő egyesítéséhez.

Gyakran Ismételt Kérdések

Melyik iOS verziótól elérhető a Combine?

Combine iOS 13, macOS 10.15, tvOS 13 és watchOS 6 verziótól elérhető. Ez korlátozza használatát olyan projektekben, amelyek régebbi verziók támogatását igénylik. iOS 12 és alatta RxSwift vagy harmadik féltől származó könyvtárak használatosak.

Miben különbözik a PassthroughSubject a CurrentValueSubject-től?

PassthroughSubject nem tárol állapotot és nem ismétli meg az utolsó értéket az új előfizetőknek — ők csak jövőbeli eseményeket kapnak. A CurrentValueSubject tárolja az aktuális értéket és azonnal továbbítja az új előfizetőnek. A CurrentValueSubject.value lehetővé teszi az aktuális érték szinkron olvasását és írását.

Hogyan integrálódik a Combine a SwiftUI-val?

Combine a SwiftUI alapját képezi: a @Published Publisher-t generál, az ObservableObject az objectWillChange Publisher-t használja. A SwiftUI View automatikusan feliratkozik a @ObservedObject és @StateObject elemekre a Combine csővezetéken keresztül, újrarajzolva a View-t a tulajdonságok változásakor.

Mi a backpressure a Combine-ban?

Backpressure — az adatátviteli sebesség kezelésének mechanizmusa. A Subscriber tájékoztatja a Subscription-t, hogy hány értéket képes feldolgozni (demand). A Publisher nem bocsáthat ki többet a kértnél. Ez kritikus fontosságú nagy adatfolyamokkal való munkánál hálózati socketekből.

Hogyan kezelhetők a hibák a Combine-ban?

A catch operátor elkapja a hibát és lecseréli a Publisher-t egy fallback-re. A replaceError a hibát alapértelmezett értékre cseréli. A retry hiba esetén meghatározott számú alkalommal ismétli a feliratkozást. Minden operátort a subscribe elé kell helyezni a Failure miatti összeomlás elkerüléséhez.

Összefoglaló

  • Combine — beépített Apple keretrendszer reaktív programozáshoz iOS 13-tól
  • Publisher — protokoll Output és Failure értékekkel, feliratkozás után kezd működni
  • Subscriber — értékeket fogad receive segítségével demand támogatással
  • Subject (PassthroughSubject, CurrentValueSubject) — Publisher kézi eseménybeszúrással
  • Operátorok map, filter, combineLatest, debounce, catch — a csővezeték alapja
  • Backpressure demand segítségével megakadályozza a Subscriber puffer túlcsordulását
  • Válassza a Combine-t új projektekhez iOS 13-tól, RxSwift-et régebbi verziók támogatásához

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is