RxCocoa的一些基本概念
来源:互联网 发布:甜甜圈软件 编辑:程序博客网 时间:2024/06/02 07:47
RxSwift是基础,它工作于各种类型的Swift,但是并不能指定用户交互、网络请求,但是RxCocoa就可以帮助我们做这些事情。RxCocoa是一个独立的库,允许我们使用许多预置的特性,这样能够更好的与UIKit和Cocoa进行整合。RxCocoa能够让我们进行响应式网络,响应式的用户交互和绑定数据模型到UI控件。大多数的UIKit控件都有响应式扩展,都是通过rx熟悉进行使用。比如:按钮的点击,我们经常会这样写:button.rx.tap,button.rx.tap返回的是ControlEvent,ControlEvent我们可以理解为是一种特殊类型的观察者序列(Observable),它可以使用.asObservable()方法转换为Observable。
RxCocoa能够工作在多平台,iOS (iPhone, iPad, Apple Watch), Apple TV ,macOS。每个平台都有一系列自定义的封装,提供了许多UI控件的扩展和一些SDK类。比如:UITextField+Rx.swift
extension Reactive where Base: UITextField { /// Reactive wrapper for `text` property. public var text: ControlProperty<String?> { return value } /// Reactive wrapper for `text` property. public var value: ControlProperty<String?> { return UIControl.rx.value( base, getter: { textField in textField.text }, setter: { textField, value in // This check is important because setting text value always clears control state // including marked text selection which is imporant for proper input // when IME input method is used. if textField.text != value { textField.text = value } } ) } }
由上面源码可知,代码很少,主要是ControlProperty,那么ControlProperty是什么呢?:首先看一下相关的源码:
public struct ControlProperty<PropertyType> : ControlPropertyType { public typealias E = PropertyType ...省略部分源码 /// Subscribes an observer to control property values. /// /// - parameter observer: Observer to subscribe to property values. /// - returns: Disposable object that can be used to unsubscribe the observer from receiving control property values. public func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == E { return _values.subscribe(observer) } ...省略部分源码 /// - returns: `Observable` interface. public func asObservable() -> Observable<E> { return _values } /// - returns: `ControlProperty` interface. public func asControlProperty() -> ControlProperty<E> { return self } /// Binds event to user interface. /// /// - In case next element is received, it is being set to control value. /// - In case error is received, DEBUG buids raise fatal error, RELEASE builds log event to standard output. /// - In case sequence completes, nothing happens. public func on(_ event: Event<E>) { switch event { case .error(let error): bindingErrorToInterface(error) case .next: _valueSink.on(event) case .completed: _valueSink.on(event) } }}ControlProperty遵守了ControlPropertyType协议。在ControlProperty结构体中,有相应的订阅、转换为观察者序列、以及发送事件等一系列方法,由此我们可以猜测,ControlProperty既是观察者也是观察者序列。那么接下来看一下ControlPropertyType协议。
/// Protocol that enables extension of `ControlProperty`.public protocol ControlPropertyType : ObservableType, ObserverType { /// - returns: `ControlProperty` interface func asControlProperty() -> ControlProperty<E>}可以看到,ControlPropertyType遵守了ObservableType, ObserverType,所以我们可以把ControlProperty理解为一种特殊类型的subject,能够被订阅而且能够有新值的注入。对于text属性直接与UITextField的内部属性text相关联。
再看一下UILabel+Rx.swift文件
extension Reactive where Base: UILabel { /// Bindable sink for `text` property. public var text: UIBindingObserver<Base, String?> { return UIBindingObserver(UIElement: self.base) { label, text in label.text = text } } /// Bindable sink for `attributedText` property. public var attributedText: UIBindingObserver<Base, NSAttributedString?> { return UIBindingObserver(UIElement: self.base) { label, text in label.attributedText = text } } }
这里我们可以看到两个属性,text和attributedText,两个属性都与UILabel对应属性相关联,非常简单。最重要的是UIBindingObserver。那么UIBindingObserver又是什么呢?
public final class UIBindingObserver<UIElementType, Value> : ObserverType where UIElementType: AnyObject { public typealias E = Value weak var UIElement: UIElementType? let binding: (UIElementType, Value) -> Void /// Initializes `ViewBindingObserver` using public init(UIElement: UIElementType, binding: @escaping (UIElementType, Value) -> Void) { self.UIElement = UIElement self.binding = binding } /// Binds next element to owner view as described in `binding`. public func on(_ event: Event<Value>) { if !DispatchQueue.isMain { DispatchQueue.main.async { self.on(event) } return } switch event { case .next(let element): if let view = self.UIElement { binding(view, element) } case .error(let error): bindingErrorToInterface(error) case .completed: break } } /// Erases type of observer. /// /// - returns: type erased observer. public func asObserver() -> AnyObserver<Value> { return AnyObserver(eventHandler: on) }}
由上面源码可知,UIBindingObserver类似于ControlProperty,也是一种类型的观察者,主要是用于UI控件。UIBindingObserver用于绑定UI和潜在的逻辑,但是它并不能绑定错误事件。如果错误事件发送给UIBindingObserver,这会调用fatalError(),打印相应的错误信息。对于UIBindingObserver还需要注意两点:
1: 不能够绑定错误事件
2: 必须在主线程执行绑定操作
绑定观察者序列(Binding observables)
在RxCocoa中绑定是单向的,如下图:只能由生产者到接受者,不能反过来操作。生产者产生值,接受者接受值,接受者不能返回值,这是基本规则。
执行绑定操作的基础就是函数bindTo(_:)。为了绑定一个观察者序列(observable)到其它实体(实体就是subject,能够处理值也可以写值。subject是非常的重要,在Cocoa中。因为像UILabel, UITextField, and UIImageView都是可变数据,能够被设置值和获取值),接受者(receiver)必须遵守观察者协议(ObserverType)。但是bindTo(_:)不仅仅是用于绑定用户界面和潜在的数据,也可以用于其它目的,例如:你能够使用bindTo(_:)创建一个独立的过程(processes),以致于观察者序列(observable)能够触发一个subject并且执行一些后台任务而并不需要显示任何内容在屏幕上。
总而言之,bindTo(_:)就是特殊的 subscribe(_:)版本。
注意:当绑定UI控件时,RxCocoa将确认观察者序列是否被执行在主线程,如果不是,将调用fatalError()而且应用将奔溃,报错误:fatal error: Element can be bound to user interface only on MainThread.
Units
RxCocoa提供了更多高级的特性来工作于Cocoa和UIKit。超越bindTo,它提供了对于观察者序列(observables)的特殊实现。专门用于UI操作,那就是Units.Units是一群类,专业化的观察者序列,允许更加容易的写简单代码处理UI.Units官方描述:
Units also help communicate and ensure observable sequence properties across interface boundaries。
看起来有点抽象,那么考虑一些普通绑定观察者序列到用户界面控件(user interface controls)情况。为了能够更新UI,你需要经常在主线程订阅,而且你经常需要共享订阅者来绑定到多个UI组件,而且你并不想在UI的处理过程中出现错误。
由于以上的情况,所以我们来看一下Units的特性:
1: Units不能有错误出现 (Units can’t error out)
2: Units是在主线程进行监听 (Units are observed on main scheduler)
3: Units在主线程进行订阅(Units subscribe on main scheduler)
4: Units共享副作用(Units share side effects)
这些实体的存在确保了用户界面经常显示内容,而且被显示的数据经常以正确的方式处理,为了UI能够进行处理。在Units framework中有两个主要的组成部分部分:
1:ControlProperty and ControlEvent
ControlProperty遵守了ObservableType和ObserverType 协议,所以我们可以对其进行订阅,也可以发送新的值,用于专门的rx扩展,绑定数据到正确的用户界面控件。
ControlEvent是用于监听一系列的UI控件的事件,它是一种观察者序列,因为遵守了ObservableType。比如:点击键盘的return按钮。如果控件使用了UIControlEvents保持跟踪控件的当前状态,ControlEvent是可以获取的.
2:Driver
Driver是一种特殊的观察者序列,也有着跟之前相同的约束,所以它不能发送错误事件。所有的处理过程都会被确保在主线程执行,避免了在后台线程改变UI。总而言之:Units是框架中的一种可选方案,你并不一定要使用它。如果你想一些好的编译简查和敏感的UI限制,Units能够变的非常强大和节约时间,
阅读全文
0 0
- RxCocoa的一些基本概念
- RxCocoa
- java的一些基本概念
- 工作流的一些基本概念
- .net的一些基本概念
- 数字证书的一些基本概念
- 概率论的一些基本概念
- 计算机的一些基本概念
- Boosting的一些基本概念
- 一些JAVA的基本概念
- C++的一些基本概念
- zedgraph的一些基本概念
- 数字证书的一些基本概念
- SSH的一些基本概念
- java的一些基本概念
- 一些基本概念的区别
- 模式识别的一些基本概念
- 模式识别的一些基本概念
- Python time strptime()方法
- flex之selectedItem与selectedIndex的区别
- htonl()ntohl()htons()函数的全称
- js中使用正则表达式
- 冒泡排序法
- RxCocoa的一些基本概念
- sysbench简单使用介绍
- 计蒜客
- 欢迎使用CSDN-markdown编辑器
- read
- C++第二课 引用实例
- JAVA:避免重复的创建对象
- 关于upload产生神奇的%EF%BB%BF
- Java面试之数据结构的简单介绍