RxSwift 中的 Observable和它的使用方式

在 RxSwift 中,Observable 是核心概念之一,它表示一个可观察的异步序列,用于处理数据流和事件流。它是响应式编程(Reactive Programming)的核心,通过声明式的方式处理异步操作和事件驱动的编程模型。


一、Observable 的定义与作用

1.1 什么是 Observable?

Observable 是一个异步序列 ,它可以发出一系列事件(Event),包括:

  • Next(事件):携带数据的事件,可以多次发送。
  • Error(错误):表示序列因错误终止。
  • Completed(完成):表示序列正常结束。

Observable 的本质是一个生产者(Producer),它负责生成数据或事件,并通过订阅(Subscription)将这些事件传递给订阅者(Observer)。

1.2 作用

  • 处理异步操作:如网络请求、文件读写、传感器数据等。
  • 事件驱动:如按钮点击、滚动视图滑动等。
  • 数据流管理:通过操作符(Operators)对数据流进行转换、过滤、合并等操作。
  • 错误处理:统一处理异步操作中的错误。
  • 生命周期管理 :通过 Disposable 管理资源释放,避免内存泄漏。

二、Observable 的创建方式

2.1 使用 create 方法

swift 复制代码
let observable = Observable<String>.create { observer in
    observer.onNext("Hello")
    observer.onNext("World")
    observer.onCompleted()
    return Disposables.create()
}

observable.subscribe { event in
    switch event {
    case .next(let value):
        print("Received: $value)")
    case .error(let error):
        print("Error: $error)")
    case .completed:
        print("Completed")
    }
}.disposed(by: disposeBag)

2.2 使用 just 方法

swift 复制代码
let observable = Observable.just("Hello")
observable.subscribe(onNext: { value in
    print("Received: $value)")
}).disposed(by: disposeBag)

2.3 使用 from 方法

swift 复制代码
let observable = Observable.from(["A", "B", "C"])
observable.subscribe(onNext: { value in
    print("Received: $value)")
}).disposed(by: disposeBag)

2.4 使用 of 方法

swift 复制代码
let observable = Observable.of(1, 2, 3)
observable.subscribe(onNext: { value in
    print("Received: $value)")
}).disposed(by: disposeBag)

2.5 使用 empty 方法

swift 复制代码
let observable = Observable<Int>.empty()
observable.subscribe(onNext: { value in
    print("Received: $value)") // 不会触发
}, onCompleted: {
    print("Completed") // 会触发
}).disposed(by: disposeBag)

三、Observable 的事件类型

Observable 的事件类型由 Event 枚举定义:

swift 复制代码
public enum Event<Element> {
    case next(Element)       // 发送数据
    case error(Swift.Error)  // 发送错误
    case completed           // 发送完成信号
}

3.1 示例:发送不同类型的事件

swift 复制代码
let observable = Observable<String>.create { observer in
    observer.onNext("First")
    observer.onNext("Second")
    observer.onError(NSError(domain: "TestError", code: 1, userInfo: nil))
    return Disposables.create()
}

observable.subscribe(
    onNext: { value in
        print("Next: $value)")
    },
    onError: { error in
        print("Error: $error)")
    },
    onCompleted: {
        print("Completed")
    }
).disposed(by: disposeBag)

四、Observable 的生命周期

4.1 订阅(Subscribe)

订阅是 ObservableObserver 之间的桥梁。只有当有订阅者时,Observable 才会开始执行其闭包中的逻辑。

swift 复制代码
observable.subscribe { event in
    // 处理事件
}.disposed(by: disposeBag)

4.2 错误处理

  • onError :当 Observable 发生错误时触发,序列终止。
  • catchError:捕获错误并继续执行。
swift 复制代码
observable
    .catchError { error in
        print("Caught error: $error)")
        return Observable.just("Recovered")
    }
    .subscribe(onNext: { value in
        print("Recovered value: $value)")
    })
    .disposed(by: disposeBag)

4.3 完成(Completed)

  • onCompleted :当 Observable 正常结束时触发。
swift 复制代码
observable.subscribe(
    onNext: { value in
        print("Next: $value)")
    },
    onCompleted: {
        print("Sequence completed")
    }
).disposed(by: disposeBag)

五、Observable 的操作符(Operators)

5.1 map:数据转换

swift 复制代码
Observable.of(1, 2, 3)
    .map { $0 * 2 }
    .subscribe(onNext: { value in
        print("Mapped: $value)")
    })
    .disposed(by: disposeBag)

5.2 filter:过滤数据

swift 复制代码
Observable.of(1, 2, 3, 4, 5)
    .filter { $0 % 2 == 0 }
    .subscribe(onNext: { value in
        print("Filtered: $value)")
    })
    .disposed(by: disposeBag)

5.3 flatMap:扁平化嵌套数据流

swift 复制代码
Observable.of(1, 2, 3)
    .flatMap { number -> Observable<String> in
        return Observable.just("Number: $number)")
    }
    .subscribe(onNext: { value in
        print("Flattened: $value)")
    })
    .disposed(by: disposeBag)

5.4 zip:合并多个数据流

swift 复制代码
let a = Observable.of(1, 2, 3)
let b = Observable.of("A", "B")

Observable.zip(a, b)
    .subscribe(onNext: { number, letter in
        print("Zipped: $number) - $letter)")
    })
    .disposed(by: disposeBag)

六、冷 Observable 与热 Observable

6.1 冷 Observable(Cold Observable)

  • 每次订阅都会独立执行闭包。
  • 适用于一次性任务(如网络请求)。
swift 复制代码
let cold = Observable<Int>.create { observer in
    observer.onNext(1)
    return Disposables.create()
}
cold.subscribe { value in
    print("Cold 1: $value)")
}.disposed(by: disposeBag)

cold.subscribe { value in
    print("Cold 2: $value)")
}.disposed(by: disposeBag)

6.2 热 Observable(Hot Observable)

  • 共享事件流,所有订阅者共享同一个事件源。
  • 适用于实时事件(如传感器数据、UI事件)。
swift 复制代码
let hot = PublishSubject<Int>()
hot.onNext(1)

hot.subscribe { value in
    print("Hot 1: $value)")
}.disposed(by: disposeBag)

hot.onNext(2)

hot.subscribe { value in
    print("Hot 2: $value)")
}.disposed(by: disposeBag)

hot.onNext(3)

七、资源管理与 Disposable

7.1 Disposable

  • 用于取消订阅或释放资源。
  • 通过 DisposeBag 管理多个 Disposable
swift 复制代码
let disposeBag = DisposeBag()

Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
    .subscribe(onNext: { value in
        print("Value: $value)")
    })
    .disposed(by: disposeBag)

7.2 Disposables.create

  • 创建一个空的 Disposable,用于释放资源。
swift 复制代码
let disposable = Disposables.create {
    print("Resource released")
}

disposable.dispose()

八、Observable 的底层原理(简要)

8.1 核心流程

  1. 创建 Observable :通过 create 方法创建一个 AnonymousObservable 实例。
  2. 订阅 Observable :调用 subscribe 方法,创建一个 Observer 并绑定到 Observable
  3. 发送事件Observable 通过 Observer 发送 nexterrorcompleted 事件。
  4. 处理事件:订阅者(Observer)接收并处理事件。
  5. 释放资源 :通过 Disposable 释放资源。

8.2 关键类

  • AnonymousObservable:匿名 Observable,由 create 方法生成。
  • ObserverType:定义了如何处理事件。
  • Disposable:用于管理资源释放。
  • Scheduler:控制事件的执行线程。

九、完整示例代码

swift 复制代码
import UIKit
import RxSwift
import RxCocoa

class ObservableExampleViewController: UIViewController {
    
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupExamples()
    }
    
    private func setupExamples() {
        // 1. 使用 create 创建 Observable
        let customObservable = Observable<String>.create { observer in
            observer.onNext("Hello")
            observer.onNext("World")
            observer.onCompleted()
            return Disposables.create()
        }
        
        customObservable.subscribe { event in
            switch event {
            case .next(let value):
                print("Custom: $value)")
            case .error(let error):
                print("Error: $error)")
            case .completed:
                print("Completed")
            }
        }.disposed(by: disposeBag)
        
        // 2. 使用 just 创建 Observable
        Observable.just("Single Value")
            .subscribe(onNext: { value in
                print("Just: $value)")
            })
            .disposed(by: disposeBag)
        
        // 3. 使用 from 创建 Observable
        Observable.from(["A", "B", "C"])
            .subscribe(onNext: { value in
                print("From: $value)")
            })
            .disposed(by: disposeBag)
        
        // 4. 使用 of 创建 Observable
        Observable.of(1, 2, 3)
            .subscribe(onNext: { value in
                print("Of: $value)")
            })
            .disposed(by: disposeBag)
        
        // 5. 使用 zip 合并多个 Observable
        let a = Observable.of(1, 2, 3)
        let b = Observable.of("A", "B")
        
        Observable.zip(a, b)
            .subscribe(onNext: { number, letter in
                print("Zip: $number) - $letter)")
            })
            .disposed(by: disposeBag)
        
        // 6. 使用 map 转换数据
        Observable.of(1, 2, 3)
            .map { $0 * 2 }
            .subscribe(onNext: { value in
                print("Map: $value)")
            })
            .disposed(by: disposeBag)
        
        // 7. 使用 filter 过滤数据
        Observable.of(1, 2, 3, 4, 5)
            .filter { $0 % 2 == 0 }
            .subscribe(onNext: { value in
                print("Filter: $value)")
            })
            .disposed(by: disposeBag)
        
        // 8. 使用 flatMap 扁平化数据流
        Observable.of(1, 2, 3)
            .flatMap { number -> Observable<String> in
                return Observable.just("Number: $number)")
            }
            .subscribe(onNext: { value in
                print("FlatMap: $value)")
            })
            .disposed(by: disposeBag)
        
        // 9. 错误处理示例
        let errorObservable = Observable<String>.create { observer in
            observer.onNext("First")
            observer.onError(NSError(domain: "TestError", code: 1, userInfo: nil))
            return Disposables.create()
        }
        
        errorObservable
            .catchError { error in
                print("Caught error: $error)")
                return Observable.just("Recovered")
            }
            .subscribe(onNext: { value in
                print("Recovered value: $value)")
            })
            .disposed(by: disposeBag)
        
        // 10. 冷 Observable 示例
        let cold = Observable<Int>.create { observer in
            observer.onNext(1)
            return Disposables.create()
        }
        cold.subscribe { value in
            print("Cold 1: $value)")
        }.disposed(by: disposeBag)
        
        cold.subscribe { value in
            print("Cold 2: $value)")
        }.disposed(by: disposeBag)
        
        // 11. 热 Observable 示例
        let hot = PublishSubject<Int>()
        hot.onNext(1)
        
        hot.subscribe { value in
            print("Hot 1: $value)")
        }.disposed(by: disposeBag)
        
        hot.onNext(2)
        
        hot.subscribe { value in
            print("Hot 2: $value)")
        }.disposed(by: disposeBag)
        
        hot.onNext(3)
    }
}
相关推荐
终端安全笔记4 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程4 小时前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne10 小时前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记1 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩1 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年1 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_916008891 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp
HouWan2 天前
Flutter: MediaQuery.of(context) 为什么可能拖慢页面?
android·flutter·ios
用户38034165882972 天前
Broadcast Extension 里的 Live Activity:一次跨进程妥协
ios·音视频开发
匠测AI说2 天前
XCUITest 自动化全解:同进程白盒、XCTest 架构、自动同步机制与 iOS 端选型指南
测试工具·ios·自动化