初探RxSwift
RxSwift: ReactiveX for Swift
官方地址: https://github.com/ReactiveX/RxSwift
ReactiveX(简写: Rx) 是一个可以帮助我们简化异步编程的框架。
RxSwift 是 Rx 的 Swift 版本。
它尝试将原有的一些概念移植到 iOS/macOS 平台。
你可以在这里找到跨平台文档 ReactiveX.io。
KVO,异步操作 和 流 全部被统一成抽象序列。这就是为什么 Rx 会如此简单,优雅和强大。
必备条件
* Xcode 10.2
* Swift 5.0
对于 Xcode 10.1 以下版本,请使用 RxSwift 4.5。
安装
安装 RxSwift 不需要任何第三方依赖。
以下是当前支持的安装方法:
手动
打开 Rx.xcworkspace, 选中 RxExample 并且点击运行。 此方法将构建所有内容并运行示例应用程序。
CocoaPods
pod --version: 1.3.1 已通过测试
# Podfile use_frameworks! target 'YOUR_TARGET_NAME' do pod 'RxSwift', '~> 5.0' pod 'RxCocoa', '~> 5.0' end # RxTests 和 RxBlocking 将在单元/集成测试中起到重要作用 target 'YOUR_TESTING_TARGET' do pod 'RxBlocking', '~> 5.0' pod 'RxTest', '~> 5.0' end
替换 YOUR_TARGET_NAME 然后在 Podfile 目录下, 终端输入:
$ pod install
Carthage
官方支持 0.33 及以上版本。
添加到 Cartfile
github "ReactiveX/RxSwift" ~> 5.0
$ carthage update
Carthage 作为静态库。
如果您希望使用 Carthage 将 RxSwift 构建为静态库,在使用 Carthage 构建之前,您可以使用以下脚本手动修改框架类型:
carthage update RxSwift --platform iOS --no-build sed -i -e 's/MACH_O_TYPE = mh_dylib/MACH_O_TYPE = staticlib/g' Carthage/Checkouts/RxSwift/Rx.xcodeproj/project.pbxproj carthage build RxAlamofire --platform iOS
Swift Package Manager
创建Package.swift 文件。
// swift-tools-version:5.0 import PackageDescription let package = Package( name: "RxTestProject", dependencies: [ .package(url: "https://github.com/ReactiveX/RxSwift.git", from: "5.0.0") ], targets: [ .target(name: "RxTestProject", dependencies: ["RxSwift", "RxCocoa"]) ] ) $ swift build
如果构建或测试一个模块对 RxTest 存在依赖, 设置 TEST=1.
$ TEST=1 swift test
使用 git submodules 手动集成
* 添加 RxSwift 作为子模块
$ git submodule add git@github.com:ReactiveX/RxSwift.git
* 拖拽 Rx.xcodeproj 到项目中
* 前往 Project > Targets > Build Phases > Link Binary With Libraries, 点击 + 并且选中 RxSwift-[Platform] 和 RxCocoa-[Platform]
为什么要使用 RxSwift ?
我们先看一下 RxSwift 能够帮助我们做些什么:
Target Action
传统实现方法:
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) func buttonTapped() { print("button Tapped") }
通过 Rx 来实现:
button.rx.tap .subscribe(onNext: { print("button Tapped") }) .disposed(by: disposeBag)
代理
传统实现方法:
class ViewController: UIViewController { ... override func viewDidLoad() { super.viewDidLoad() scrollView.delegate = self } } extension ViewController: UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { print("contentOffset: \(scrollView.contentOffset)") } }
通过 Rx 来实现:
class ViewController: UIViewController { ... override func viewDidLoad() { super.viewDidLoad() scrollView.rx.contentOffset .subscribe(onNext: { contentOffset in print("contentOffset: \(contentOffset)") }) .disposed(by: disposeBag) } }
你不需要书写代理的配置代码,就能获得想要的结果。
闭包回调
传统实现方法:
URLSession.shared.dataTask(with: URLRequest(url: url)) { (data, response, error) in guard error == nil else { print("Data Task Error: \(error!)") return } guard let data = data else { print("Data Task Error: unknown") return } print("Data Task Success with count: \(data.count)") }.resume()
通过 Rx 来实现:
URLSession.shared.rx.data(request: URLRequest(url: url)) .subscribe(onNext: { data in print("Data Task Success with count: \(data.count)") }, onError: { error in print("Data Task Error: \(error)") }) .disposed(by: disposeBag)
回调也变得十分简单
通知
传统实现方法:
var ntfObserver: NSObjectProtocol! override func viewDidLoad() { super.viewDidLoad() ntfObserver = NotificationCenter.default.addObserver( forName: .UIApplicationWillEnterForeground, object: nil, queue: nil) { (notification) in print("Application Will Enter Foreground") } } deinit { NotificationCenter.default.removeObserver(ntfObserver) }
通过 Rx 来实现:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.rx .notification(.UIApplicationWillEnterForeground) .subscribe(onNext: { (notification) in print("Application Will Enter Foreground") }) .disposed(by: disposeBag) }
你不需要去管理观察者的生命周期,这样你就有更多精力去关注业务逻辑。
多个任务之间有依赖关系
例如,先通过用户名密码取得 Token 然后通过 Token 取得用户信息,
传统实现方法:
/// 用回调的方式封装接口 enum API { /// 通过用户名密码取得一个 token static func token(username: String, password: String, success: (String) -> Void, failure: (Error) -> Void) { ... } /// 通过 token 取得用户信息 static func userinfo(token: String, success: (UserInfo) -> Void, failure: (Error) -> Void) { ... } } /// 通过用户名和密码获取用户信息 API.token(username: "beeth0ven", password: "987654321", success: { token in API.userInfo(token: token, success: { userInfo in print("获取用户信息成功: \(userInfo)") }, failure: { error in print("获取用户信息失败: \(error)") }) }, failure: { error in print("获取用户信息失败: \(error)") })
通过 Rx 来实现:
/// 用 Rx 封装接口 enum API { /// 通过用户名密码取得一个 token static func token(username: String, password: String) -> Observable<String> { ... } /// 通过 token 取得用户信息 static func userInfo(token: String) -> Observable<UserInfo> { ... } } /// 通过用户名和密码获取用户信息 API.token(username: "beeth0ven", password: "987654321") .flatMapLatest(API.userInfo) .subscribe(onNext: { userInfo in print("获取用户信息成功: \(userInfo)") }, onError: { error in print("获取用户信息失败: \(error)") }) .disposed(by: disposeBag)
这样你可以避免回调地狱,从而使得代码易读,易维护。
等待多个并发任务完成后处理结果
例如,需要将两个网络请求合并成一个,
通过 Rx 来实现:
/// 用 Rx 封装接口 enum API { /// 取得老师的详细信息 static func teacher(teacherId: Int) -> Observable<Teacher> { ... } /// 取得老师的评论 static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... } } /// 同时取得老师信息和老师评论 Observable.zip( API.teacher(teacherId: teacherId), API.teacherComments(teacherId: teacherId) ).subscribe(onNext: { (teacher, comments) in print("获取老师信息成功: \(teacher)") print("获取老师评论成功: \(comments.count) 条") }, onError: { error in print("获取老师信息或评论失败: \(error)")
})
.disposed(by: disposeBag)
这样你可用寥寥几行代码来完成相当复杂的异步操作。
那么为什么要使用 RxSwift ?
复合 - Rx 就是复合的代名词
复用 - 因为它易复合
清晰 - 因为声明都是不可变更的
易用 - 因为它抽象的了异步编程,使我们统一了代码风格
稳定 - 因为 Rx 是完全通过单元测试的

浙公网安备 33010602011771号