البرمجة التفاعلية في Swift: Combine و RxSwift لنظامي iOS/macOS

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

البرمجة التفاعلية في Swift (iOS/macOS): Combine و RxSwift

البرمجة التفاعلية هي نموذج يعتمد على العمل مع تدفقات البيانات غير المتزامنة ونشر التغييرات. في نظام Apple البيئي لنظامي iOS و macOS، الأدوات الرئيسية هي إطار العمل الأصلي Combine (من iOS 13/macOS 10.15) والمكتبة الخارجية RxSwift. كلاهما يسمح بكتابة كود تصريحي، موجز، وسهل الاختبار، مما يريح المطور من "جحيم الاسترجاعات" وإدارة الحالة المعقدة.



المفاهيم الأساسية

  • الناشر (Publisher) — مصدر البيانات الذي يمكنه إرسال القيم، الإكمال، أو الخطأ.
  • المشترك (Subscriber) — يستقبل البيانات من الناشر ويستجيب لها.
  • عامل التشغيل (Operator) — دالة لتحويل التدفق (map، filter، combineLatest، debounce وغيرها).
  • الموضوع (Subject) — هجين يمكنه استقبال وإرسال الأحداث (PassthroughSubject، CurrentValueSubject).
  • المجدول (Scheduler) — يحدد في أي تدفق (Thread) يتم تنفيذ الكود.


Combine: إطار Apple الأصلي

Combine مدمج في Foundation ويعمل مع Publisher و Subscriber. مثال على استخدامه لمعالجة حقل نصي:

import Combineimport UIKit

class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private var cancellables = Set<AnyCancellable>()

override func viewDidLoad() { super.viewDidLoad() // إنشاء ناشر من NotificationCenter let publisher = NotificationCenter.default .publisher(for: UITextField.textDidChangeNotification, object: textField) .compactMap { ($0.object as? UITextField)?.text } .debounce(for: .milliseconds(500), scheduler: RunLoop.main) .removeDuplicates() // الاشتراك publisher .sink { [weak self] value in self?.label.text = "لقد أدخلت: \\(value)" } .store(in: &cancellables) }}

في المثال، يتم استخدام debounce لتأخير الاستجابة للإدخال و removeDuplicates لتجاهل القيم المكررة.



RxSwift: بديل قوي

RxSwift هو نسخة من ReactiveX للغة Swift. يقدم مجموعة أوسع من عوامل التشغيل ويدعم إصدارات أقدم من iOS. نفس المثال باستخدام RxSwift:

import RxSwiftimport RxCocoa

class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var label: UILabel! private let disposeBag = DisposeBag()

override func viewDidLoad() { super.viewDidLoad() textField.rx.text .orEmpty .debounce(.milliseconds(500), scheduler: MainScheduler.instance) .distinctUntilChanged() .subscribe(onNext: { [weak self] text in self?.label.text = "لقد أدخلت: \\(text)" }) .disposed(by: disposeBag) }}

لاحظ استخدام rx.text (عبر RxCocoa) و distinctUntilChanged() — وهو مماثل لـ removeDuplicates في Combine.



عوامل التشغيل الرئيسية

  • map / compactMap — تحويل القيم.
  • filter — يمرر فقط القيم التي تحقق الشرط.
  • combineLatest — يدمج أحدث القيم من عدة تدفقات.
  • zip — يدمج العناصر بشكل زوجي من عدة تدفقات.
  • flatMap — يحول التدفق إلى تدفق آخر (يستخدم غالبًا لطلبات الشبكة).
  • catch / retry — معالجة الأخطاء.

توصيات