RxSwift — یک کتاخانه برنامهنویسی راکتشی برای iOS است که الگوی Observable و عاملهای تابعی را برای کار با جریانهای داده اسینکرون پیاده میکند. مفاهیم ReactiveX (Rx) را به زبان Swift منتقل میکند و یک API واحد برای پردازش رویدادهای UI، درخواستهای شبکه، پایگاه داده و تایمرها ارائه میدهد. بر اساس ReactiveX, 2025، این کتاخانه در بیش از 60,000 پروژه در GitHub مورد استفاده قرار گرفته و تا ظهور Combine اصلی برنامهنویسی راکتشی برای Swift باقی مانده است. RxSwift دلگاتها، بستهها و اطلاعرسانیها را با یک زنجیره واحد پردازش رویداد جایگزین میکند.
نکات اصلی
RxSwift — پورت Swift از کتاخانه ReactiveX (Rx) است که توسط شرکت Microsoft برای .NET در سال 2012 ساخته شد. ایده اصلی Rx — تمام منابع داده اسینکرون را به عنوان یک تسلسل Observable نمایش دهیم که میتوان عاملهای تابعی را به آن اعمال کرد. در توسعه iOS، RxSwift برای اتصال رویدادهای UI (کلیک دکمه، ورود متن، اشارات) به منطق برنامه بدون دلگاتهای صریح و تارگت-اکشن استفاده میشود.
کتاخانه از سه ماژول تشکیل شده: RxSwift (هسته — Observable، Operator، Scheduler)، RxCocoa (ادغام با UIKit — افزونههای rx برای UIButton، UITextField، UITableView) و RxRelay (Subject بدون رویدادهای پایانی). این تقسیم امکان استفاده از هسته در Swift سرور و آزمایشها و اتصال پیوست UI را فقط برای برنامههای iOS فراهم میکند.
بر اساس نظرسنجی Stack Overflow، 2025، RxSwift در طبقه بندی 5 کتاخانه برتر شخص ثالث برای iOS قرار دارد. دلیل اصلی محبوبیت — پردازش یکسان تمام الگوهای اسینکرون: درخواستهای شبکه از طریق URLSession، انیمیشنها از طریق UIViewPropertyAnimator، اطلاعرسانیها از طریق NotificationCenter و دلگاتها از طریق DelegateProxy — همه چیز به Observable با چرخه عمر قابل پیشبینی تبدیل میشود.
برنامهنویسی راکتشی — پارادایمی است که در آن برنامه به تغییرات دادهها واکنش نشان میدهد، نه آنها را پرسیش میکند. به جای نوشتن «دادهها را بگیر → پردازش کن → UI را بهروز کن»، برنامهنویس یک زنجیره تبدیل را توصیف میکند: «وقتی دادهها تغییر کردند، فیلتر را اعمال کن، سپس map، سپس UI را بهروز کن». RxSwift این پارادایم را از طریق زنجیرههای Observable با اجرای تنبل پیاده میکند — تا مشترکی ظاهر نشود، هیچ چیزی اتفاق نمیافتد.
Observable — نوع بنیادین RxSwift که یک تسلسل رویداد را در زمان نمایش میدهد. Observable میتواند سه نوع رویداد ارسال کند: next (مقدار جدید)، error (خطا، پایان جریان) و completed (پایان موفقیتآمیز). Observableهای finite (پس از ارسال تمام مقادیر پایان مییابند) و infinite (مثلاً رویدادهای UI — هرگز پایان نمییابند) وجود دارند.
چرخه عمر Observable شامل سه مرحله است: ایجاد (create، just، from)، تبدیل (عاملهای map، filter، flatMap) و اشتراک (subscribe). بدون اشتراک، Observable هیچ فعالیتی انجام نمیدهد — این یک تسلسل تنبل است. پس از اشتراک، Observable شروع به ارسال رویدادها به مشترک میکند تا زمانی که تمام نشود یا مشترک اشتراک را از طریق Disposable لغو نکند.
import RxSwift
// ایجاد Observable از ماتریس
let numbers = Observable.from([1, 2, 3, 4, 5])
// تبدیل از طریق عاملها
let squared = numbers
.filter { $0 % 2 == 0 }
.map { $0 * $0 }
// اشتراک با پردازش رویداد
let disposable = squared
.subscribe(onNext: { print($0) },
onError: { print("Error: \($0)") },
onCompleted: { print("Done") })
Subject — نوعی است که همزمان Observable (میتوان بر آن مشترک شد) و Observer (میتوان به آن رویداد ارسال کرد) است. RxSwift چهار نوع Subject ارائه میدهد: PublishSubject (تنها رویدادهای جدید)، BehaviorSubject (با مقدار اولیه)، ReplaySubject (بافر آخرین N رویداد) و AsyncSubject (تنها آخرین مقدار قبل از پایان). Subject برای ادغام کد امری (بستهها، دلگاتها) در زنجیره راکتشی مفید است.
Disposable — توکن لغو اشتراک است. وقتی مشترک دیگر نمیخواهد رویدادها را دریافت کند، disposable.dispose() را صدا میزند. در عمل، DisposeBag استفاده میشود: مجموعهای از Disposable که پس از از بین رفتن صاحب (مثلاً UIViewController) بهطور خودکار تمام اشتراکها را لغو میکند. این از نشت حافظه جلوگیری میکند که در مدیریت دستی اشتراکها اجتنابناپذیر است.
| نوع Subject | مقدار اولیه | به مشترک تکرار میکند | کاربرد |
|---|---|---|---|
| PublishSubject | نخیر | تنها رویدادهای جدید | رویدادهای UI، اطلاعرسانیهای نادر |
| BehaviorSubject | بله | آخرین + جدید | وضعیت، جریان داده |
| ReplaySubject | نخیر | بافر N + جدید | ذخیره تاریخچه |
| AsyncSubject | نخیر | تنها آخرین | وظایف محاسباتی |
| PublishRelay | نخیر | تنها جدید | بدون error/completed |
عاملهای RxSwift — توابعی هستند که یک Observable را گرفته و Observable دیگری را با تبدیل جریان داده بازمیگردانند. با ترکیب عاملها، برنامهنویس زنجیرههای پردازش تصریحی را بدون متغیرهای واسطه و شرایط مسابقه میسازد. تمام عاملها تنبل هستند: زنجیره در زمان توصیف ساخته شده و در زمان اشتراک اجرا میشود.
عاملهای تبدیل هر رویداد در جریان را تغییر میدهند. map به هر عنصر یک تابع اعمال میکند، flatMap Observable حاصل از هر عنصر را به یک جریان تخت تبدیل میکند، scan نتیجه واسطه را جمع میکند (مشابه reduce والی با انتشار هر مرحله). buffer عناصر را بر اساس زمان یا تعداد گروهبندی میکند، window جریان را به Observableهای تودرتو تقسیم میکند.
// مثال زنجیره عاملها: جستجو با 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)
عاملهای فیلتر تنها رویدادهایی را که شرط را برآورده میکنند اجازه میدهند. filter بر اساس پرودیکیت جدا میکند، distinctUntilChanged تنها مقادیر متفاوت از قبلی را اجازه میدهد، take و takeWhile تعداد رویدادها را محدود میکنند. skip و skipWhile اولین N رویداد یا رویدادهای تا تحقق شرط را نادیده میگیرند. برای پردازش خطا از catchError (گرفتن و جایگزینی) و retry (تکرار تسلسل در خطا) استفاده میشود.
عاملهای ترکیب چند Observable را در یکی ترکیب میکنند. combineLatest آخرین مقادیر از چند جریان را در یک کرتپل ترکیب میکند، zip عناصر را با شاخصهای یکسان جفت میکند، merge چند جریان را به ترتیب ورود رویدادها ترکیب میکند. withLatestFrom رویداد از جریان اصلی را با آخرین مقدار از جریان دیگر ترکیب میکند — برای رویدادهای UI با وضعیت فعلی مفید است.
| دسته | عامل | کارکرد |
|---|---|---|
| تبدیل | map | هر مقدار را از طریق تابع تبدیل میکند |
| تبدیل | flatMap | Observableهای تودرتو را به جریان تخت تبدیل میکند |
| فیلتر | filter | مقادیر را بر اساس پرودیکیت اجازه میدهد |
| فیلتر | distinctUntilChanged | تنها مقادیر تغییریافته را اجازه میدهد |
| ترکیب | combineLatest | آخرین مقادیر از 2+ جریان را ترکیب میکند |
| ترکیب | zip | عناصر را به صورت جفت از روی شاخص ترکیب میکند |
| مدیریت | debounce | رویدادها را تا مکث در جریان به تأخیر میاندازد |
| مدیریت | take | اولین N رویداد را گرفته و جریان را پایان میدهد |
Scheduler در RxSwift — یک چکیدهسازی بر رشته اجرا (یا صف) است. Scheduler مشخص میکند که ایجاد رویداد، تبدیل و اشتراک در کدام رشته انجام شود. به عکس GCD که برنامهنویس DispatchQueue را صریحاً مشخص میکند، RxSwift از دو پارامتر استفاده میکند: subscribeOn (روی چه رشتهای Observable اجرا شود) و observeOn (روی چه رشتهای مشترک صدا زده شود).
MainScheduler کد را در رشته اصلی اجرا میکند — برای بهروزرسانی UIKit اجباری است (تمام تغییرات UI باید در main thread انجام شود). SerialDispatchQueueScheduler یک صف توالیی GCD را میپیچوند، ConcurrentDispatchQueueScheduler یک صف موازی را. برای وظایف پسزمینه از ConcurrentDispatchQueueScheduler با qos: .background یا .utility استفاده میشود.
// الگوی معمولی: کار پسزمینه + UI در main
apiService.fetchData()
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.observeOn(MainScheduler.instance)
.subscribe(onNext: { data in
self.tableView.reloadData()
self.loadingIndicator.stopAnimating()
})
.disposed(by: disposeBag)
استفاده صحیح از Scheduler از بلوکـه شدن UI در زمان درخواستهای شبکه و محاسبات سنگین جلوگیری میکند. subscribeOn بر کل upstream تأثیر میگذارد (تمام عاملها تا observeOn در زمانبندی مشخص اجرا میشوند). observeOn داناستریم را تغییر میدهد — تمام عاملها پس از observeOn در زمانبندی مشخص اجرا میشوند. در زنجیره میتواند چندین observeOn برای تغییر بین رشتهها در مراحل مختلف تبدیل وجود داشته باشد.
SerialDispatchQueueScheduler پردازش متوالی رویدادها را تضمین میکند که برای امنیت رشته منابع مشترک اهم است. برای عملیات پربار (پردازش تصویر، تجزیه و تحلیل JSON) از ConcurrentDispatchQueueScheduler استفاده کنید — RxSwift ترتیب رویدادها را در ون واحد Observable حفظ میکند، اما Observableهای مختلف میتوانند به صورت موازی پردازش شوند.
RxSwift در پروژههای iOS بیشتر برای اتصال UI با دادهها از طریق زنجیرههای راکتشی استفاده میشود. RxCocoa برای تمام کامپوننتهای استاندارد UIKit افزونههای rx ارائه میدهد: rx.tap برای UIButton، rx.text برای UITextField، rx.selectedRow برای UIPickerView. این امکان انکار از @IBAction و دلگاتها و جایگزینی آنها با اشتراکهای تصریحی را فراهم میکند.
MVVM (Model-View-ViewModel) — الگوی معماری که در آن ViewModel وضعیت و منطق کسب و کار را مدیریت میکند و View در ویژگیهای راکتشی ViewModel مشترک میشود. RxSwift بهطور کامل در MVVM جای میگیرد: ViewModel Observable یا Driver را برای دادهها منتشر میکند و View از طریق bind در آنها مشترک میشود. ViewModel به View ارجاعی ندارد — Observable را بازمیگرداند که View مصرف میکند.
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
}
}
}
// در ViewController:
viewModel.isFormValid
.bind(to: loginButton.rx.isEnabled)
.disposed(by: disposeBag)
درخواستهای شبکه — دومین حوزه کاربردی RxSwift. URLSession.rx.response یک درخواست HTTP را در Observable میپیچوند که در صورت موفقیت (response, data) و در صورت شکست error بازمیگرداند. در ترکیب با Codable و عامل map، یک لایه API راکتشی مترکم داریم: Observable<MyModel> بدون callback و پردازش خطا در هر روش. در خطای شبکه، عامل retry(3) درخواست را بهطور خودکار سه بار با تأخیر نمایی تکرار میکند.
Combine — چارچوب ذاتی Apple است که در iOS 13 معرفی شد. همان مسائل را به عنوان RxSwift حل میکند: کار با رویدادهای اسینکرون از طریق Publisher، Subscriber و عاملها. اما Combine تفاوتهای کلیدی دارد: نوعبندی سختگیرانه خطاها از طریق نوع Failure، پشتیبانی ذاتی از Swift Concurrency (async/await) و ادغام با SwiftUI از طریق @Published و ObservableObject.
RxSwift در سازگاری به عقب پیروز میشود — iOS 8+ را پشتیبانی میکند، در حالیکه Combine به iOS 13+ نیاز دارد. RxSwift اکوسیستم غنیتری از افزونههای شخص ثالث (RxDataSources، RxGesture، RxAnimated) و مستندات مفصل عاملها را داراست. برای پروژههایی که از نسخهای قدیمی iOS پشتیبانی میکنند، RxSwift تنها گزینه ممکن است.
برای پروژههای جدید با iOS 13+، Apple Combine را توصیه میکند. آن بهطور گسترده با SwiftUI ادغام شده، اندازه باینری کوچکتری دارد و پشتیبانی رسمی دارد. اما مهاجرت کد موجود RxSwift به Combine نیازمند بازنویسی تمام Observable → Publisher است و اکوسیستم RxCocoa در Combine معادل کاملی ندارد — UIKit برای تمام کامپوننتهای UI خود Publisher ذاتی ندارد.
| ویژگی | RxSwift | Combine |
|---|---|---|
| حداقل iOS | iOS 8+ | iOS 13+ |
| نوع خطا | Error (هر نوعی) | Generic Failure |
| افزونههای UI | RxCocoa (UIKit، AppKit) | @Published (SwiftUI) |
| عاملها | 400+ عامل | ~100 عامل |
| Swift Concurrency | از طریق پل | پشتیبانی ذاتی |
| وضعیت | شخص ثالث | رسمی Apple |
سوالات متداول
Observable — منبع رویداد با اجرای تنبل. Subject همزمان Observable و Observer است — میتوانید در آن مشترک شوید و به طور دستی رویدادهای جدید به آن ارسال کنید. Subject برای ادغام کد امری در زنجیرههای راکتشی مفید است.
RxSwift در صورت نیاز به پشتیبانی iOS 11-12، وجود کدبان موجود RxSwift یا نیاز به اکوسیستم غنی عاملها (400+ در مقابل ~100 در Combine) انتخاب میشود. برای پروژههای جدید در iOS 13+ ترجیح با Combine است.
DisposeBag — کلکسیونی از توکنهای Disposable است که بهطور خودکار تمام اشتراکها را پس از از بین رفتن صاحب لغو میکند. بدون DisposeBag، اشتراک یک ارجاع قوی به بسته ایجاد میکند که به نشت حافظه پس از نابودی UIViewController منجر میشود.
از catchError برای جایگزینی خطا با مقدار پیشفرض، retry برای اجرای مجدد Observable، materialize برای تبدیل خطا به رویداد استفاده کنید. در لایه UI، Driver و Signal خطاها را انتقال نمیدهند — داخلی پردازش میشوند.
Driver — نوع ویژهای از Observable است که اجرا روی MainScheduler، بدون خطا و اشتراک منابع را تضمین میکند. Driver تضمین میدهد که بهروزرسانیهای UI در رشته اصلی انجام شوند. Observable چنین تضمیناتی نمیدهد — observeOn مورد نیاز است.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید