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 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.
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 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.
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.
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 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.
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.
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.
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.
Az első példa az alapvető munkát mutatja Just — Publisher, amely egy értéket bocsát ki és befejeződik:
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:
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:
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
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.
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
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.
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.
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.
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.
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ó
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.
Olvassa el is