响应式编程,响应式编程是一种面向数据流和变化传播的编程方式式,简单理解就是异步的数据流的开发。html
特色是将函数做为一等公民,看成参数和返回值使用。典型的如OC和Swift 中的 map函数、filter函数、reduce函数等。每一个函数的处理结果给到下一个函数,最后的结果由自身函数调出。git
传统实现方法:github
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) 复制代码
你不须要使用 Target Action,这样使得代码逻辑清晰可见。swift
传统实现方法:缓存
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() scrollView.delegate = self } } extension ViewController: UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { print("contentOffset: \(scrollView.contentOffset)") } } 复制代码
经过 Rx 来实现:bash
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() scrollView.rx.contentOffset .subscribe(onNext: { contentOffset in print("contentOffset: \(contentOffset)") }) .disposed(by: disposeBag) } } 复制代码
你不须要书写代理的配置代码,就能得到想要的结果。markdown
传统实现方法:网络
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) 复制代码
回调也变得十分简单
传统实现方法:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(updateNotificationStatus), name: UIApplication.willEnterForegroundNotification, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } // MARK: - Notification @objc func updateNotificationStatus(){ print("Application Will Enter Foreground") } 复制代码
经过 Rx 来实现:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.rx.notification(UIApplication.willEnterForegroundNotification) .subscribe(onNext: { (notification) in print("Application Will Enter Foreground") }).disposed(by: disposeBag) } 复制代码
你不须要去管理观察者的生命周期,这样你就有更多精力去关注业务逻辑。
传统实现方法:
private var observerContext = 0 override func viewDidLoad() { super.viewDidLoad() user.addObserver(self, forKeyPath: #keyPath(User.name), options: [.new, .initial], context: &observerContext) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if context == &observerContext { let newValue = change?[.newKey] as? String print("do something with newValue") } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) } } deinit { user.removeObserver(self, forKeyPath: #keyPath(User.name)) } 复制代码
经过 Rx 来实现:
override func viewDidLoad() { super.viewDidLoad() user.rx.observe(String.self, #keyPath(User.name)) .subscribe(onNext: { newValue in print("do something with newValue") }) .disposed(by: disposeBag) } 复制代码
这样实现 KVO 的代码更清晰,更简洁而且更准确。
例如,先经过用户名密码取得 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 能够在 UniDirectional Data Flow 的各个阶段都发挥做用,从而让 Data 的处理和流动更加简洁和清晰。
MVVM 是 Model-View-ViewModel 的缩写。
一样使用 MVVM 架构时,Model 与 View|ViewControllter 之间是不容许直接通讯的,而是由 ViewModel 层进行协调
// 声明一个枚举,包含成功和失败的状况 enum TWSwiftHttpResult { case success(Any) //成功 case failure(String) //失败 case noNet() //无网络 } // 使用RxSwift进行扩展 extension Reactive where Base: TWSwiftHttpTool { /// 基于YYCache 缓存的RXSwift 请求方式 static func request(type: TWRequestType, url: String, parameters: [AnyHashable: Any]?, flag: Bool = true, isCache: Bool = false, cacheKey: String? = nil, cacheBlock: (CacheBlock)? = nil) -> Observable<Any> { return Observable.create { observer in let task = TWSwiftHttpTool.request(type: type, url: url, flag: flag, parameters: parameters, isCache: isCache, cacheKey: cacheKey, cacheBlock: cacheBlock, complete: { (result) in dealComplete(result: result, observer: observer) }) return Disposables.create(with: task.cancel) } } // MARK: - Private Common Method private static func dealComplete(result:TWSwiftHttpResult,observer:AnyObserver<Any>) { switch result { case .success(let response): observer.onNext(response) observer.onCompleted() case .failure(let reason): // observer.onNext([TWSwiftErrorMsg:reason]) observer.onError(RxNetworkError.general(reason)) case .noNet: // observer.onNext([TWSwiftErrorMsg:TWSwiftNoNetMsg]) observer.onError(RxNetworkError.noNet) } } } 复制代码
//订阅输入输出协议 protocol TWSwiftViewModelProtocol { associatedtype TWSwiftInput associatedtype TWSwiftOutput func transform(input: TWSwiftInput) -> TWSwiftOutput } //viewModel实现TWSwiftViewModelProtocol的协议 extension NewHouseWeekViewModel:TWSwiftViewModelProtocol{ typealias TWSwiftInput = Input typealias TWSwiftOutput = Output // MARK: - Override Method struct Input { //便是订阅又是被订阅 let requestId = PublishSubject<String>() } struct Output { //输出数据源 let sections: Driver<[NewHouseWeekSectionModel]> //成功输出 let successSubject = PublishSubject<String>() //错误输出 let errorSubject = PublishSubject<String>() init(sections: Driver<[NewHouseWeekSectionModel]>) { self.sections = sections } } func transform(input: NewHouseWeekViewModel.Input) -> NewHouseWeekViewModel.Output { ``` } } 复制代码
/// viewModel绑定 fileprivate func bindViewModel() { let vmInput = NewHouseWeekViewModel.Input() ///输入 let vmOutput = viewModel.transform(input: vmInput) ///输出 ///数据源绑定到tableview中 vmOutput.sections.asDriver().drive(tableView.rx.items(dataSource: dataSource)).disposed(by: TWSwiftDisposeBag) ///错误订阅 vmOutput.errorSubject.subscribe(onNext:{[weak self] (errorMsg) in self?.hideHud(in: self?.tableView, hint: errorMsg) self?.setEmptyDic() }).disposed(by: TWSwiftDisposeBag) ///成功订阅 vmOutput.successSubject.subscribe(onNext: nil, onError: nil, onCompleted: {[weak self] in self?.hideHUD() self?.setEmptyDic() }, onDisposed: nil).disposed(by: TWSwiftDisposeBag) let regionId = TWSwiftGuardNullString(GlobalObject.share()?.regionId) ///发起数据请求 vmInput.requestId.onNext(regionId) self.showActivityIndicatorSuperView(tableView) } 复制代码
理解响应链的编程思路 RxSwift给咱们带来最大影响的Reactive思想,OOP告诉咱们,在编写应用程序的时候,要考虑的是对象有什么,对象作什么,对象与对象之间的联系,而Reactive思想将对象所作的都当作是数据流,咱们关注的是事件自己的影响。