RxSwift — шта је то, кључни концепти и реактивно програмирање

Аутор: IT Sectr Објављено: 2026-03-17 Време читања: 8 мин

RxSwift је библиотека реактивног програмирања за Swift, која имплементира образац Observable. Према подацима ReactiveX, 2025, ово је најпопуларнија имплементација Reactive Extensions за Apple екосистем. Observable представља извор догађаја, а Observer се претплаћује на њихово примање.

Главно

  • RxSwift — имплементација Reactive Extensions за Swift са подршком за Observable, Subject и 300+ оператора
  • Observable — извор догађаја који емитује вредности, грешке или сигнал завршетка
  • Subject — истовремено Observable и Observer, омогућава ручно уметање догађаја у ток
  • DisposeBag — механизам аутоматског управљања меморијом, који отказује претплате при деалокацији
  • Schedulers — управљају нитима извршења, омогућавајући пребацивање између main и background редова

Шта је RxSwift?

RxSwift је библиотека реактивног програмирања за језик Swift, пренесена из Reactive Extensions (Rx). Омогућава описивање асинхроних и догађајно-оријентисаних програма кроз Observable Sequence — секвенцу података доступних током времена. iOS програмери користе RxSwift за обраду мрежних захтева, UI догађаја и токова података без угнеждених callback-а.

Observable и Observer

Основу RxSwift-а чине два кључна протокола: ObservableType — извор догађаја који може емитовати три врсте сигнала: .next(value), .error(error) и .completed. Observer се претплаћује на Observable путем методе subscribe и прима ове догађаје. Такав модел се назива Reactive Streams и гарантује да ниједан догађај неће бити изгубљен уз исправну претплату.

Оператори трансформације

RxSwift пружа преко 300 оператора за рад са токовима: map трансформише сваки догађај, filter пропушта само одговарајуће, flatMap размотава угнеждене Observable-е у јединствени ток. Оператори се комбинују у ланце, стварајући декларативни цевовод обраде података без споредних ефеката.

Traits: Single, Completable, Maybe

Поред основног Observable-а, RxSwift пружа специјализоване типове омотача. Single емитује тачно једну вредност или грешку — идеалан за HTTP захтеве. Completable се завршава успехом или грешком без вредности — за операције уписа. Maybe комбинује оба сценарија: може се завршити са вредношћу, без вредности или са грешком. Ови Traits поједностављују семантику и чине код самодокументујућим.

Како ради реактивно програмирање у RxSwift-у

Реактивно програмирање у RxSwift-у се заснива на обрасцу Observer. ObservableSequence је аналог Sequence-а из стандардне библиотеке, али са асинхроним приступом елементима. Ток догађаја се преноси кроз ланац оператора, од којих сваки враћа нову ObservableSequence, не мењајући оригиналну.

Ланци оператора

Оператори у RxSwift-у су чисте функције које примају једну ObservableSequence и враћају нову. На пример, map ствара нову секвенцу примењујући трансформацију на сваки елемент. Комбинујући операторе, програмер гради цевовод у којем подаци пролазе кроз све фазе обраде без међуваријабли.

Schedulers и нити извршења

Schedulers је апстракција над нитима извршења у RxSwift-у. Scheduler одређује на којој нити ће се код извршавати: MainScheduler — UI нит, SerialDispatchQueueScheduler — позадински ред. Оператори subscribeOn и observeOn одређују где се посао обавља и где се обрађују резултати.

Основне компоненте RxSwift-а

RxSwift укључује неколико основних типова, од којих сваки решава свој задатак у реактивном цевоводу. Single — Observable који емитује тачно једну вредност или грешку, погодан за мрежне захтеве. Completable се завршава успехом или грешком без вредности. Maybe комбинује особине Single и Completable.

Subject и Relay

Subject је врући Observable који истовремено делује као Observer. PublishSubject емитује само нове догађаје претплатницима, BehaviorSubject — последњи догађај плус нове. Relay је варијанта Subject-а која не емитује .error или .completed, гарантујући непрекидност тока. BehaviorRelay чува тренутну вредност и погодан је за State-driven UI.

DisposeBag

DisposeBag је колекција Disposable-а која аутоматски отказује све претплате при својој деалокацији. У iOS-у, DisposeBag се обично додаје у UIViewController или UIView. При затварању екрана, DisposeBag се чисти — ово спречава цурење меморије и позивање на непостојеће UI елементе.

Примери кода RxSwift

Испод је приказан пример креирања Observable-а из низа података коришћењем оператора map за трансформацију стрингова:

swift
let observable = Observable.of("Swift", "RxSwift", "Reactive")

observable
    .map { $0.uppercased() }
    .subscribe(onNext: { value in
        print("Примљено: \(value)")
    })
    .disposed(by: disposeBag)

У другом примеру се демонстрира спајање два мрежна захтева помоћу zip — оператор чека док оба Observable-а емитују вредност и комбинује резултате у уређени пар:

swift
let first = fetchUser(id: "123")
let second = fetchPosts(userId: "123")

Observable
    .zip(first, second)
    .observe(on: MainScheduler.instance)
    .subscribe(onNext: { user, posts in
        updateUI(user: user, posts: posts)
    })
    .disposed(by: disposeBag)

Трећи пример показује употребу BehaviorRelay за чување стања и аутоматско ажурирање UI-ја при променама: свака измена state.accept() се одмах преноси претплатницима, што је идеално за State обрасце у MVVM архитектури.

swift
let state = BehaviorRelay(value: "idle")

state
    .subscribe(onNext: { status in
        print("Статус: \(status)")
    })
    .disposed(by: disposeBag)

state.accept("loading") // Исписаће: Статус: loading

RxSwift у односу на друге приступе

RxSwift се разликује од традиционалних метода асинхроности (Delegation, NotificationCenter, Callback) декларативношћу и композибилношћу. За разлику од Combine-а, RxSwift подржава iOS 9+ и има више оператора. Међутим, Combine је интегрисан у Foundation и SwiftUI на нивоу језика, што му даје предност у новим Apple пројектима.

Главна предност RxSwift-а над GCD-ом (Grand Central Dispatch) — могућност комбиновања и трансформисања токова података на нивоу апстракције, а не ручног управљања редовима. Истовремено, RxSwift захтева учење концепата реактивног приступа, што повећава праг уласка за тим.

У пракси, RxSwift се користи у великим пројектима где реактивни ланци повезују UI догађаје, пословну логику и мрежне интеракције у јединствени цевовод. На пример, у трговачким апликацијама токови котација се обрађују кроз RxSwift: тикови долазе из WebSocket-а, пролазе филтрацију, групишу се по временском оквиру и приказују на графикону у реалном времену. Такав сценариј је тешко реализовати кроз Delegation или NotificationCenter без губитка читљивости.

Алтернативе RxSwift-у укључују Combine (iOS 13+), AsyncSequence из Swift Concurrency (iOS 15+), као и библиотеку ReactiveSwift без везивања за Apple платформе. Избор зависи од минималне подржане iOS верзије и искуства програмера. За нове пројекте iOS 15+, тимови често бирају AsyncSequence — не захтева инсталацију библиотека и користи природне конструкције језика Swift.

Архитектонски обрасци са RxSwift-ом обично прате MVVM или Clean Architecture. ViewModel садржи сву пословну логику у облику Observable ланаца, View се претплаћује на трансформисане податке. Input-Output образац раздваја улазне догађаје (додири, унос текста) и излазна стања (текст дугмета, видљивост loader-а). Овај приступ поједностављује тестирање: ViewModel се тестира без UI-ја кроз виртуелне Scheduler-е.

RxSwift је погодан како за мале пројекте са пар екрана, тако и за велике enterprise апликације са десетинама модула. У великим пројектима, реактивни ланци прожимају целу архитектуру: од посматрања UserDefaults-а кроз RxProperty до мрежних захтева кроз Moya (RxSwift омотач над Alamofire-ом). Сваки модул је изолован и комуницира кроз реактивне интерфејсе, што поједностављује замену имплементације без мењања претплатника. Са исправном архитектуром, RxSwift смањује количину кода у поређењу са класичним приступима, јер није потребно писати boilerplate за KVO, Target-Action или NotificationCenter.

RxSwift се активно користи у пројектима са RxDataSources — библиотеком за реактивни рад са UITableView и UICollectionView. RxDataSources аутоматски израчунава разлику између старог и новог скупа ћелија и примењује анимиране промене. Ово ослобађа програмера ручног рада са beginUpdates/endUpdates и елиминише падове при неусклађености података.

За отклањање грешака у RxSwift ланцима постоји оператор debug() — бележи све догађаје: subscribe, next, error, completed, dispose. Ово је незаменљив алат при развоју сложених реактивних цевовода. debug(String) прима идентификатор који се приказује у логовима. За профилисање меморије, RxSwift.Resources.total показује укупан број активних Observable и Disposable у апликацији — помаже у откривању цурења када DisposeBag није очишћен или retain cycle држи претплату. Додатни оператор takeUntil(self.rx.deallocated) аутоматски отказује претплату при деалокацији објекта — ово је још један слој заштите од цурења меморије.

Најбоље праксе RxSwift-а

При писању RxSwift кода важно је поштовати принцип један Observable по претплати: сваки ViewController не треба да ствара више од једне претплате на један Observable — ово смањује ризик од race condition-а. За мемоизацију Observable-а користи се оператор share(), који хладни Observable претвара у врући са replay-бафером величине 1. При раду са дељеним ресурсима користите connect() за управљање почетком емисије — ово гарантује да се сви претплатници повежу пре првог догађаја.

Тестирање RxSwift кода се изводи кроз TestScheduler — виртуелни Scheduler који омогућава управљање временом. testScheduler.createHotObservable(values) ствара Observable са унапред дефинисаном секвенцом догађаја по виртуелном времену. testScheduler.start() покреће обраду. TestScheduler омогућава проверу редоследа и виртуелног временског жига на којем се догађаји дешавају, без стварних кашњења, што чини тестове брзим и детерминистичким.

Често постављана питања

Која је разлика између Observable-а и Subject-а у RxSwift-у?

Observable је хладни извор: не емитује догађаје до претплате. Subject је врући: емитује догађаје независно од претплатника и омогућава ручно убацивање вредности кроз onNext. PublishSubject преноси само нове догађаје, BehaviorSubject — последњи плус нове.

Како DisposeBag спречава цурење меморије у RxSwift-у?

DisposeBag чува све Disposable претплате. Када се DisposeBag деалоцира (на пример, при затварању ViewController-а), све сачуване претплате се аутоматски отказују. Ово гарантује да Observable више неће послати догађај већ уништеном UI објекту.

Шта изабрати: RxSwift или Combine у новом iOS пројекту?

Ако је минимална верзија iOS 13+ и тим зна SwiftUI — изаберите Combine. Ако пројекат подржава iOS 12 и ниже или захтева већи скуп оператора — RxSwift. Combine пружа бољу интеграцију са Foundation-ом (URLSession, Timer, NotificationCenter).

Како раде Schedulers у RxSwift-у?

Schedulers апстрахују нити извршења. subscribeOn указује на ком Scheduler-у се извршава претплата (обично background). observeOn одређује на ком Scheduler-у се примају догађаји (чешће MainScheduler за UI ажурирања). SerialDispatchQueueScheduler ради кроз GCD.

Може ли се RxSwift користити са SwiftUI-јем?

Да, RxSwift се може интегрисати са SwiftUI-јем кроз ObservableObject. Користите BehaviorRelay као @Published својства: претплата на Relay преноси измене у Combine, а SwiftUI поново исцртава View кроз @ObservedObject. Ово је популаран образац миграције са UIKit-а на SwiftUI.

Закључци

  • RxSwift — библиотека реактивног програмирања заснована на Reactive Extensions и Observable обрасцу
  • Observable емитује три врсте сигнала: .next, .error и .completed
  • Subject (PublishSubject, BehaviorSubject) комбинује Observable и Observer за вруће токове
  • DisposeBag управља животним циклусом претплата и спречава цурење меморије
  • Оператори (map, filter, flatMap, zip) омогућавају изградњу декларативних ланаца обраде
  • Schedulers пребацују извршење између позадинских редова и UI нити
  • За нови развој на iOS 13+, размотрите Combine као уграђену алтернативу

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође