RxSwift är ett bibliotek för reaktiv programmering för iOS som implementerar Observable-mönstret och funktionella operatorer för att arbeta med asynkrona dataströmmar. Den porterar koncepten från ReactiveX (Rx) till språket Swift och tillhandahåller ett enhetligt API för att hantera händelser från UI, nätverksförfrågningar, databaser och timers. Enligt ReactiveX, 2025 används biblioteket i över 60 000 projekt på GitHub och förblir standarden för reaktiv programmering för Swift fram till ankomsten av inbyggt Combine. RxSwift ersätter delegater, closures och meddelanden med en enhetlig händelsehanteringskedja.
Huvudpunkter
RxSwift är Swift-porten av ReactiveX-biblioteket (Rx) som skapades av Microsoft för .NET 2012. Huvudidén med Rx är att presentera varje asynkron datakälla som en Observable-sekvens som funktionella operatorer kan tillämpas på. I iOS-utveckling används RxSwift för att koppla UI-händelser (knapptryckningar, textinmatning, gester) till applikationslogik utan explicita delegater och target-action.
Biblioteket består av tre moduler: RxSwift (kärna — Observable, Operator, Scheduler), RxCocoa (integration med UIKit — rx-tillägg för UIButton, UITextField, UITableView) och RxRelay (Subject utan terminala händelser). Denna uppdelning gör det möjligt att använda kärnan i server-Swift och tester, och ansluta UI-endast för iOS-applikationer.
Enligt enkäten Stack Overflow, 2025 är RxSwift bland de 5 mest använda tredjepartsbiblioteken för iOS. Huvudorsaken till populariteten är enhetlig hantering av alla asynkrona mönster: nätverksförfrågningar via URLSession, animationer via UIViewPropertyAnimator, meddelanden via NotificationCenter och delegater via DelegateProxy — allt reduceras till Observable med förutsägbar livscykel.
Reaktiv programmering är ett paradigm där programmet reagerar på dataförändringar istället för att polla dem. Istället för att skriva ”hämta data → bearbeta → uppdatera UI”, beskriver utvecklaren en transformationskedja: ”när data ändras, tillämpa filter, sedan map, sedan uppdatera UI”. RxSwift implementerar detta paradigm genom Observable kedjor med lat exekvering — ingenting händer förrän en prenumerant dyker upp.
Observable är den grundläggande typen i RxSwift som representerar en sekvens av händelser över tid. Observable kan skicka tre typer av händelser: next (nytt värde), error (fel, avslutar strömmen) och completed (framgångsrikt slutförande). Det finns finite Observable (avslutas efter att ha skickat alla värden) och infinite Observable (t.ex. UI-händelser — avslutas aldrig).
Livscykeln för Observable omfattar tre faser: skapande (create, just, from), transformation (operatorer map, filter, flatMap) och prenumeration (subscribe). Utan prenumeration utför Observable inga åtgärder — det är en lat sekvens. Efter prenumeration börjar Observable skicka händelser till prenumeranten tills den avslutas eller prenumeranten avbryter prenumerationen via Disposable.
import RxSwift
// Skapa Observable från array
let numbers = Observable.from([1, 2, 3, 4, 5])
// Transformation genom operatorer
let squared = numbers
.filter { $0 % 2 == 0 }
.map { $0 * $0 }
// Prenumerera med händelsehantering
let disposable = squared
.subscribe(onNext: { print($0) },
onError: { print("Error: \($0)") },
onCompleted: { print("Done") })
Subject är en typ som samtidigt är Observable (kan prenumereras på) och Observer (kan skicka händelser till). RxSwift erbjuder fyra typer av Subject: PublishSubject (endast nya händelser), BehaviorSubject (med initialvärde), ReplaySubject (buffring av de senaste N händelserna) och AsyncSubject (endast sista värdet före avslutning). Subject är praktiskt för integration av imperativ kod (closures, delegater) i reaktiva kedjor.
Disposable är en token för att avbryta prenumeration. När prenumeranten inte längre vill ta emot händelser anropar den disposable.dispose(). I praktiken används DisposeBag: en samling Disposable som automatiskt avbryter alla prenumerationer vid deinitialisering av ägaren (t.ex. UIViewController). Detta förhindrar minnesläckor som är oundvikliga vid manuell hantering av prenumerationer.
| Subject-typ | Initialvärde | Upprepar för prenumerant | Användning |
|---|---|---|---|
| PublishSubject | Nej | Endast nya händelser | UI-händelser, sällsynta meddelanden |
| BehaviorSubject | Ja | Senaste + nya | Tillstånd, dataström |
| ReplaySubject | Nej | Buffert N + nya | Cachelagring av historik |
| AsyncSubject | Nej | Endast sista | Beräkningsuppgifter |
| PublishRelay | Nej | Endast nya | Utan error/completed |
Operatorer i RxSwift är funktioner som tar en Observable och returnerar en annan Observable, vilket transformerar dataströmmen. Genom att kombinera operatorer bygger utvecklaren deklarativa bearbetningskedjor utan mellanliggande variabler och race condition. Alla operatorer är lata: kedjan byggs vid beskrivning och exekveras vid prenumeration.
Transformationsoperatorer ändrar varje händelse i strömmen. map tillämpar en funktion på varje element, flatMap vecklar ut Observable från varje element till en platt ström, scan ackumulerar mellanresultat (analogt med reduce men med utsändning av varje steg). buffer grupperar element efter tid eller kvantitet, window delar strömmen i nästlade Observable per fönster.
// Exempel på operatorkedja: sökning med debounce
searchTextField.rx.text
.orEmpty
.debounce(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query -> Observable<[String]> in
return apiService.search(query)
}
.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, item, cell in
cell.textLabel?.text = item
}
.disposed(by: disposeBag)
Filteroperatorer släpper bara igenom de händelser som uppfyller villkoret. filter sållar efter predikat, distinctUntilChanged släpper bara igenom värden som skiljer sig från föregående, take och takeWhile begränsar antalet händelser. skip och skipWhile hoppar över de första N händelserna eller händelser tills villkoret uppfylls. För felhantering används catchError (fånga och ersätta) och retry (upprepa sekvensen vid fel).
Kombinationsoperatorer slår samman flera Observable till en. combineLatest kombinerar de senaste värdena från flera strömmar till en tupel, zip kombinerar element parvis med samma index, merge slår samman flera strömmar till en i den ordning händelserna anländer. withLatestFrom kombinerar en händelse från huvudströmmen med det senaste värdet från en annan ström — praktiskt för UI-händelser med aktuellt tillstånd.
| Kategori | Operator | Vad den gör |
|---|---|---|
| Transformation | map | Transformerar varje värde genom en funktion |
| Transformation | flatMap | Vecklar ut nästlade Observable till platt ström |
| Filtrering | filter | Släpper igenom värden baserat på predikat |
| Filtrering | distinctUntilChanged | Släpper bara igenom ändrade värden |
| Kombination | combineLatest | Kombinerar senaste värden från 2+ strömmar |
| Kombination | zip | Kombinerar element parvis efter index |
| Hantering | debounce | Fördröjer händelser tills paus i strömmen |
| Hantering | take | Tar de första N händelserna och avslutar strömmen |
Scheduler i RxSwift är en abstraktion över en exekveringstråd (eller kö). Scheduler bestämmer på vilken tråd skapande av händelser, transformation och prenumeration utförs. Till skillnad från GCD där utvecklaren explicit anger DispatchQueue använder RxSwift två parametrar: subscribeOn (på vilken tråd Observable exekveras) och observeOn (på vilken tråd prenumeranten anropas).
MainScheduler exekverar kod på huvudtråden — obligatoriskt för uppdatering av UIKit (alla UI-ändringar måste ske på main thread). SerialDispatchQueueScheduler omsluter en sekventiell GCD-kö, ConcurrentDispatchQueueScheduler en parallell kö. För bakgrundsuppgifter används ConcurrentDispatchQueueScheduler med qos: .background eller .utility.
// Typiskt mönster: bakgrundsarbete + UI på main
apiService.fetchData()
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
self.tableView.reloadData()
self.loadingIndicator.stopAnimating()
})
.disposed(by: disposeBag)
Korrekt användning av Scheduler förhindrar UI-blockering vid nätverksförfrågningar och tunga beräkningar. subscribeOn påverkar hela upstream (alla operatorer fram till observeOn exekveras på angiven schemaläggare). observeOn växlar downstream — alla operatorer efter observeOn exekveras på angiven schemaläggare. I kedjan kan det finnas flera observeOn för att växla mellan trådar vid olika transformationsstadier.
RxSwift i iOS-projekt används oftast för att koppla UI till data genom reaktiva kedjor. RxCocoa tillhandahåller rx-tillägg för alla standard UIKit-komponenter: rx.tap för UIButton, rx.text för UITextField, rx.selectedRow för UIPickerView. Detta gör det möjligt att ersätta @IBAction och delegater med deklarativa prenumerationer.
MVVM (Model-View-ViewModel) är ett arkitekturmönster där ViewModel hanterar tillstånd och affärslogik, och View prenumererar på ViewModels reaktiva egenskaper. RxSwift passar perfekt in i MVVM: ViewModel publicerar Observable eller Driver för data, View prenumererar på dem via bind. ViewModel har ingen referens till View — den returnerar Observable som View konsumerar.
class LoginViewModel {
let email = BehaviorRelay<String>(value: "")
let password = BehaviorRelay<String>(value: "")
var isFormValid: Observable<Bool> {
return Observable
.combineLatest(email, password) {
!$0.isEmpty && $0.contains("@") && $1.count >= 6
}
}
}
// I ViewController:
viewModel.isFormValid
.bind(to: loginButton.rx.isEnabled)
.disposed(by: disposeBag)
Nätverksförfrågningar är det näst vanligaste användningsområdet för RxSwift. URLSession.rx.response omsluter en HTTP-förfrågan i en Observable som returnerar (response, data) vid framgång eller error vid misslyckande. I kombination med Codable och operatorn map får vi ett kompakt reaktivt API-lager: Observable<MyModel> utan callbacks och felhantering i varje metod. Vid nätverksfel upprepar operatorn retry(3) automatiskt förfrågan tre gånger med exponentiell fördröjning.
Combine är ett inbyggt Apple-ramverk som introducerades i iOS 13. Det löser samma uppgifter som RxSwift: arbete med asynkrona händelser via Publisher, Subscriber och operatorer. Combine har dock viktiga skillnader: strikt typning av fel via Failure-typen, inbyggt stöd för Swift Concurrency (async/await) och integration med SwiftUI via @Published och ObservableObject.
RxSwift vinner i bakåtkompatibilitet — det stödjer iOS 8+, medan Combine kräver iOS 13+. RxSwift har ett rikare ekosystem av tredjepartstillägg (RxDataSources, RxGesture, RxAnimated) och detaljerad operatordokumentation. För projekt som stödjer äldre iOS-versioner förblir RxSwift det enda valet.
För nya projekt med iOS 13+ rekommenderar Apple Combine. Det är tätt integrerat med SwiftUI, har mindre binärstorlek och officiellt stöd. Migrering av befintlig RxSwift-kod till Combine kräver dock omskrivning av alla Observable → Publisher, och RxCocoa-ekosystemet har ingen fullständig motsvarighet i Combine — UIKit har inga inbyggda Publisher för alla UI-komponenter.
| Egenskap | RxSwift | Combine |
|---|---|---|
| Minsta iOS | iOS 8+ | iOS 13+ |
| Feltyp | Error (godtycklig) | Generic Failure |
| UI-tillägg | RxCocoa (UIKit, AppKit) | @Published (SwiftUI) |
| Operatorer | 400+ operatorer | ~100 operatorer |
| Swift Concurrency | Via brygga | Inbyggt stöd |
| Status | Tredjepart | Officiellt Apple |
Vanliga frågor
Observable är en händelsekälla med lat exekvering. Subject är samtidigt Observable och Observer — du kan prenumerera på det och manuellt skicka nya händelser till det. Subject är praktiskt för integration av imperativ kod i reaktiva kedjor.
RxSwift väljs vid behov av stöd för iOS 11-12, vid befintlig RxSwift-kodbas eller vid behov av ett rikt operatorekosystem (400+ mot ~100 i Combine). För nya projekt på iOS 13+ är Combine att föredra.
DisposeBag är en samling Disposable-tokens som automatiskt avbryter alla prenumerationer vid deinitialisering av ägaren. Utan DisposeBag skapar prenumerationen en stark referens till closuren, vilket leder till minnesläckor när UIViewController förstörs.
Använd catchError för att ersätta ett fel med ett standardvärde, retry för att köra om Observable, materialize för att omvandla ett fel till en händelse. I UI-lagret skickar Driver och Signal inte fel — de hanteras internt.
Driver är en speciell Observable-typ som garanterar exekvering på MainScheduler, frånvaro av fel och delning av resurser. Driver garanterar att UI-uppdateringar sker på huvudtråden. Observable ger inga sådana garantier — observeOn krävs.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också