RxSwift文档补充二(Delegate)
DelegateProxyType
View只能注册一个delegate/datasource,而DelegateProxyType
协议允许使用正常的delegates
和Rx观察序列。
Proxies
为特定的视图存储有关observers、subscriptions和delegates的信息。
DelegateProxyType
的实现不能直接初始化,应该使用获取实现DelegateProxyType
、proxy
初始化实例的方法。
这或多或少就是DelegateProxyType
的工作原理:
+-------------------------------------------+
| |
| UIView subclass (UIScrollView) |
| |
+-----------+-------------------------------+
|
| Delegate
|
|
+-----------v-------------------------------+
| |
| Delegate proxy : DelegateProxyType +-----+----> Observable<T1>
| , UIScrollViewDelegate | |
+-----------+-------------------------------+ +----> Observable<T2>
| |
| +----> Observable<T3>
| |
| forwards events |
| to custom delegate |
| v
+-----------v-------------------------------+
| |
| Custom delegate (UIScrollViewDelegate) |
| |
+-------------------------------------------+
因为RxCocoa需要自动创建那些代理,并且拥有delegates
的View可以是继承的UITableView: UIScrollView: UIView
相应的代理也是继承的UITableViewDelegate: UIScrollViewDelegate: NSObject
这个机制可以通过在使用rx.*
之前(例如appDidFinishLaunching),在registerKnownImplementations
或程序的其他一些地方使用执行下面的代码片段来扩展。
RxScrollViewDelegateProxy.register { RxTableViewDelegateProxy(parentObject: $0) }
协议分析
public protocol DelegateProxyType: class {
/// 关联类型,父对象->持有代理对象的类
associatedtype ParentObject: AnyObject
/// 关联类型,代理->上面ParentObject的代理类
associatedtype Delegate
/// 这里需要枚举调用扩展的DelegateProxy子类的`register`
static func registerKnownImplementations()
/// 代理的唯一id
static var identifier: UnsafeRawPointer { get }
/// 返回对象特定的代理属性
///
/// 对象可以有多个代理属性
///
/// 每个代理属性需要在自己的类中实现`DelegateProxyType`
///
/// 这是抽象方法
///
/// - parameter object: 拥有代理属性的对象
/// - returns: 代理属性的值
static func currentDelegate(for object: ParentObject) -> Delegate?
/// 为对象设置特定的代理属性
///
/// 对象可以有多个代理属性
///
/// 每个代理属性需要在自己的类中实现`DelegateProxyType`
///
/// 这是抽象方法
///
/// - parameter toObject: 拥有代理属性的对象
/// - parameter delegate: 代理属性的值
static func setCurrentDelegate(_ delegate: Delegate?, to object: ParentObject)
/// 返回接收所有通过`self`转发的消息的正常代理的引用
///
/// - returns: 引用的值或者为空
func forwardToDelegate() -> Delegate?
/// 设置接收所有通过`self`转发的消息的正常代理的引用
///
/// - parameter forwardToDelegate: 接收所有通过`self`转发的消息的代理的引用
/// - parameter retainDelegate: `self`是否强引用`forwardToDelegate`
func setForwardToDelegate(_ forwardToDelegate: Delegate?, retainDelegate: Bool)
}
DelegateProxy
DelegateProxy作为实现DelegateProxyType
协议的基类,它的实现不是线程安全的,只能在主线程中使用。
_RXDelegateProxy
_RXDelegateProxy
是DelegateProxy
的父类,由Objective-C实现,继承自NSObjective,.h文件如下:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface _RXDelegateProxy : NSObject
@property (nonatomic, weak, readonly) id _forwardToDelegate;
-(void)_setForwardToDelegate:(id __nullable)forwardToDelegate retainDelegate:(BOOL)retainDelegate NS_SWIFT_NAME(_setForwardToDelegate(_:retainDelegate:)) ;
-(BOOL)hasWiredImplementationForSelector:(SEL)selector;
-(BOOL)voidDelegateMethodsContain:(SEL)selector;
-(void)_sentMessage:(SEL)selector withArguments:(NSArray*)arguments;
-(void)_methodInvoked:(SEL)selector withArguments:(NSArray*)arguments;
@end
首先分析几个相关的方法函数
RX_is_method_with_description_void
函数:
BOOL RX_is_method_with_description_void(struct objc_method_description method) {
return strncmp(method.types, @encode(void), 1) == 0;
}
代码分析:
- 这个函数的作用是通过一个方法描述结构体
objc_method_description
判断此方法是否有返回值 - 使用
strncmp
函数比较方法参数编码字符串和void
的类型编码的第一个字符是否相等
collectVoidSelectorsForProtocol:
方法:
+(NSSet*)collectVoidSelectorsForProtocol:(Protocol *)protocol {
NSMutableSet *selectors = [NSMutableSet set];
unsigned int protocolMethodCount = 0;
struct objc_method_description *pMethods = protocol_copyMethodDescriptionList(protocol, NO, YES, &protocolMethodCount);
for (unsigned int i = 0; i < protocolMethodCount; ++i) {
struct objc_method_description method = pMethods[i];
if (RX_is_method_with_description_void(method)) {
[selectors addObject:SEL_VALUE(method.name)];
}
}
free(pMethods);
unsigned int numberOfBaseProtocols = 0;
Protocol * __unsafe_unretained * pSubprotocols = protocol_copyProtocolList(protocol, &numberOfBaseProtocols);
for (unsigned int i = 0; i < numberOfBaseProtocols; ++i) {
[selectors unionSet:[self collectVoidSelectorsForProtocol:pSubprotocols[i]]];
}
free(pSubprotocols);
return selectors;
}
代码分析:
- 此方法的作用是返回一个协议及其继承的协议中定义的所有没有返回值的方法的集合
- 获取该协议上定义的所有方法,将没有返回值的方法的
selector
转换为一个NSValue
值加入到集合中 - 获取该协议继承的所有协议,合并通过递归的方式获取协议上定义的所有没有返回值的方法的集合,然后返回
主要方法分析
initialize
方法是在这个类接收第一条消息之前调用:
+(void)initialize {
@synchronized (_RXDelegateProxy.class) {
if (voidSelectorsPerClass == nil) {
voidSelectorsPerClass = [[NSMutableDictionary alloc] init];
}
NSMutableSet *voidSelectors = [NSMutableSet set];
#define CLASS_HIERARCHY_MAX_DEPTH 100
NSInteger classHierarchyDepth = 0;
Class targetClass = NULL;
for (classHierarchyDepth = 0, targetClass = self;
classHierarchyDepth < CLASS_HIERARCHY_MAX_DEPTH && targetClass != nil;
++classHierarchyDepth, targetClass = class_getSuperclass(targetClass)
) {
unsigned int count;
Protocol *__unsafe_unretained *pProtocols = class_copyProtocolList(targetClass, &count);
for (unsigned int i = 0; i < count; i++) {
NSSet *selectorsForProtocol = [self collectVoidSelectorsForProtocol:pProtocols[i]];
[voidSelectors unionSet:selectorsForProtocol];
}
free(pProtocols);
}
if (classHierarchyDepth == CLASS_HIERARCHY_MAX_DEPTH) {
NSLog(@"Detected weird class hierarchy with depth over %d. Starting with this class -> %@", CLASS_HIERARCHY_MAX_DEPTH, self);
#if DEBUG
abort();
#endif
}
voidSelectorsPerClass[CLASS_VALUE(self)] = voidSelectors;
}
}
代码分析:
- 可变字典类型的静态变量
voidSelectorsPerClass
在没有值时初始化 - 遍历该类的继承系统,然后遍历每个类遵守的协议,使用上面分析的
collectVoidSelectorsForProtocol:
方法拿到协议定义的没有返回值的方法集合然后合并到一起 - 最后将该类转化为
NSValue
值做为key,将上面得到的集合作为值存储到voidSelectorsPerClass
字典中
_forwardToDelegate取值方法:
-(id)_forwardToDelegate {
return __forwardToDelegate;
}
代码分析:
- 只读属性
_forwardToDelegate
的getter方法,直接返回实例变量__forwardToDelegate
的值
_setForwardToDelegate:retainDelegate:
方法:
-(void)_setForwardToDelegate:(id __nullable)forwardToDelegate retainDelegate:(BOOL)retainDelegate {
__forwardToDelegate = forwardToDelegate;
if (retainDelegate) {
self.strongForwardDelegate = forwardToDelegate;
}
else {
self.strongForwardDelegate = nil;
}
}
代码分析:
- 把
forwardToDelegate
赋值给实例变量__forwardToDelegate
- 根据
retainDelegate
决定是否把forwardToDelegate
赋值给strongForwardDelegate
强引用属性
非常重要的一个方法forwardInvocation:
-(void)forwardInvocation:(NSInvocation *)anInvocation {
BOOL isVoid = RX_is_method_signature_void(anInvocation.methodSignature);
NSArray *arguments = nil;
if (isVoid) {
arguments = RX_extract_arguments(anInvocation);
[self _sentMessage:anInvocation.selector withArguments:arguments];
}
if (self._forwardToDelegate && [self._forwardToDelegate respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:self._forwardToDelegate];
}
if (isVoid) {
[self _methodInvoked:anInvocation.selector withArguments:arguments];
}
}
代码分析:
- 该方法是在接受到一个未知消息进行消息转发时调用的,可以移步我以前的一篇博客了解消息转发
- 首先判断未知消息是否有返回值
- 如果该未知消息没有返回值就获取消息的参数列表并执行
_sentMessage:withArguments:
方法 - 如果
_forwardToDelegate
属性能够响应该消息,将该未知消息转发给_forwardToDelegate
属性对象 - 最后如果该未知消息没有返回值就执行
_methodInvoked:withArguments:
方法
DelegateProxyFactory
遵守DelegateProxyType
协议的代理对象的工厂类,主要作用是存储生成遵守DelegateProxyType
协议的代理对象的闭包。
初始化:
private var _factories: [ObjectIdentifier: ((AnyObject) -> AnyObject)]
private var _delegateProxyType: Any.Type
private var _identifier: UnsafeRawPointer
private init<DelegateProxy: DelegateProxyType>(for proxyType: DelegateProxy.Type) {
self._factories = [:]
self._delegateProxyType = proxyType
self._identifier = proxyType.identifier
}
代码分析:
-
_factories
属性使用空字典初始化 -
_delegateProxyType
属性使用遵守DelegateProxyType
协议的代理类初始化 -
_identifier
属性使用遵守DelegateProxyType
协议的代理类的id初始化
extend
函数:
fileprivate func extend<DelegateProxy: DelegateProxyType, ParentObject>(make: @escaping (ParentObject) -> DelegateProxy) {
MainScheduler.ensureRunningOnMainThread()
precondition(self._identifier == DelegateProxy.identifier, "Delegate proxy has inconsistent identifier")
guard self._factories[ObjectIdentifier(ParentObject.self)] == nil else {
rxFatalError("The factory of \(ParentObject.self) is duplicated. DelegateProxy is not allowed of duplicated base object type.")
}
self._factories[ObjectIdentifier(ParentObject.self)] = { make(castOrFatalError($0)) }
}
代码分析:
- 首先保证在主线程
- 保证
_identifier
属性的值与泛型DelegateProxy
的identifier
类属性相等 - 保证
_factories
属性字典中没有存储以泛型ParentObject
相应的ObjectIdentifier
作为key
的值 - 以泛型
ParentObject
相应的ObjectIdentifier
作为key
,将生成Rx代理对象的闭包存在_factories
属性中
createProxy
函数:
fileprivate func createProxy(for object: AnyObject) -> AnyObject {
MainScheduler.ensureRunningOnMainThread()
var maybeMirror: Mirror? = Mirror(reflecting: object)
while let mirror = maybeMirror {
if let factory = self._factories[ObjectIdentifier(mirror.subjectType)] {
return factory(object)
}
maybeMirror = mirror.superclassMirror
}
rxFatalError("DelegateProxy has no factory of \(object). Implement DelegateProxy subclass for \(object) first.")
}
代码分析:
- 首先保证在主线程
- 遍历参数对象的继承系统,用类相应的
ObjectIdentifier
作为key
从_factories
属性中获取生成Rx代理对象的闭包,取到闭包就返回执行闭包的结果 - 最终取不到闭包就终止
类属性_sharedFactories
是以代理的id作为key、工厂对象作为值的字典,用于缓存各遵守DelegateProxyType
协议的代理类的工厂对象:
private static var _sharedFactories: [UnsafeRawPointer: DelegateProxyFactory] = [:]
sharedFactory
函数根据遵守DelegateProxyType
协议的代理类的id获取对应的工厂对象,代码如下:
fileprivate static func sharedFactory<DelegateProxy: DelegateProxyType>(for proxyType: DelegateProxy.Type) -> DelegateProxyFactory {
MainScheduler.ensureRunningOnMainThread()
let identifier = DelegateProxy.identifier
if let factory = _sharedFactories[identifier] {
return factory
}
let factory = DelegateProxyFactory(for: proxyType)
_sharedFactories[identifier] = factory
DelegateProxy.registerKnownImplementations()
return factory
}
代码分析:
- 保证在主线程
- 根据遵守
DelegateProxyType
协议的代理类id从_sharedFactories
字典中获取工厂对象,取到就返回 -
_sharedFactories
字典中取不到工厂对象,就创建一个并存到字典中 - 执行遵守
DelegateProxyType
协议的代理类的registerKnownImplementations
函数并返回工厂对象
MessageDispatcher
MessageDispatcher
的本质是一个PublishSubject
,把协议中的每个函数对应一个MessageDispatcher
,进而将函数的调用转化为Observable
序列,其实现如下:
private final class MessageDispatcher {
private let dispatcher: PublishSubject<[Any]>
private let result: Observable<[Any]>
fileprivate let selector: Selector
init<P, D>(selector: Selector, delegateProxy _delegateProxy: DelegateProxy<P, D>) {
weak var weakDelegateProxy = _delegateProxy
let dispatcher = PublishSubject<[Any]>()
self.dispatcher = dispatcher
self.selector = selector
self.result = dispatcher
.do(onSubscribed: { weakDelegateProxy?.checkSelectorIsObservable(selector); weakDelegateProxy?.reset() }, onDispose: { weakDelegateProxy?.reset() })
.share()
.subscribeOn(mainScheduler)
}
var on: (Event<[Any]>) -> Void {
return self.dispatcher.on
}
var hasObservers: Bool {
return self.dispatcher.hasObservers
}
func asObservable() -> Observable<[Any]> {
return self.result
}
}
代码分析:
- 初始化时创建一个
PublishSubject
存储在dispatcher
属性中 - 初始化时将
dispatcher
属性中存储的PublishSubject
执行do
操作符,并在PublishSubject
被订阅后执行代理对象的checkSelectorIsObservable
函数检查是否能将selector
转化为Observable
序列,然后执行代理对象的reset
函数重新设置代理。在PublishSubject
销毁时执行代理对象的reset
函数重新设置代理。然后执行share
操作共享元素,接着执行subscribeOn(mainScheduler)
操作保证序列在主线程中执行各种操作,最后将最终得到的Observable
序列存储到result
属性中 -
on
函数直接调用dispatcher
属性中存储的PublishSubject
的on
操作 -
asObservable
函数直接返回初始化时构造好的result
属性
DelegateProxy实现
首先分析一下DelegateProxy
的属性:
-
_sentMessageForSelector
属性是一个以Selector
为key
以MessageDispatcher
为值的字典 -
_methodInvokedForSelector
属性也是一个以Selector
为key
以MessageDispatcher
为值的字典,与_sentMessageForSelector
相比主要是他们存储的MessageDispatcher
使用的时机不同(后面再讲) -
_parentObject
属性存储持有代理对象的对象 -
_currentDelegateFor
属性是一个闭包,用来获取_parentObject
属性的代理对象 -
_setCurrentDelegateTo
属性也是一个闭包,用来设置_parentObject
属性的代理对象
sentMessage
函数分析:
open func sentMessage(_ selector: Selector) -> Observable<[Any]> {
MainScheduler.ensureRunningOnMainThread()
let subject = self._sentMessageForSelector[selector]
if let subject = subject {
return subject.asObservable()
}
else {
let subject = MessageDispatcher(selector: selector, delegateProxy: self)
self._sentMessageForSelector[selector] = subject
return subject.asObservable()
}
}
代码分析:
- 使用
selector
参数从_sentMessageForSelector
属性中取MessageDispatcher
对象, - 取到值就转化为
Observable
序列返回 - 没有取到值就创建一个
MessageDispatcher
对象,存储到_sentMessageForSelector
属性中,然后转化为Observable
序列返回
methodInvoked
函数的实现与上面分析的函数相同。
checkSelectorIsObservable
函数分析:
- 该函数的作用是检查
selector
参数对应的函数是否能够转化为Observable
序列 - 首先检查自己没有实现
selector
参数对应的函数 - 接着检查自己遵守的协议定义的没有返回值的函数集合包含有
selector
参数对应的函数 - 最后检查
_forwardToDelegate
属性不能响应selector
参数对应的函数
_sentMessage
和_methodInvoked
函数分析:
open override func _sentMessage(_ selector: Selector, withArguments arguments: [Any]) {
self._sentMessageForSelector[selector]?.on(.next(arguments))
}
open override func _methodInvoked(_ selector: Selector, withArguments arguments: [Any]) {
self._methodInvokedForSelector[selector]?.on(.next(arguments))
}
代码分析:
-
_sentMessage
和_methodInvoked
函数都只是取出对应的MessageDispatcher
对象,然后执行on
操作来发射元素 - 此时应该联系
DelegateProxy
的父类_RXDelegateProxy
的forwardInvocation:
方法来分析 - 在收到没有返回值的未知消息时,会先后执行这两个方法(注意它们的执行顺序)
DelegateProxyType扩展重要函数实现
register
函数就是把生成对象闭包存储到DelegateProxyFactory
中:
private static var factory: DelegateProxyFactory {
return DelegateProxyFactory.sharedFactory(for: self)
}
public static func register<Parent>(make: @escaping (Parent) -> Self) {
self.factory.extend(make: make)
}
代码分析:
-
DelegateProxyFactory.sharedFactory
首次调用时内部会调用registerKnownImplementations
函数 - 前面说过需要在实现
registerKnownImplementations
函数时调用实现的代理类的register
函数注册一个代理对象生成的闭包 -
DelegateProxyFactory
的extend
函数就是用来存储代理对象生成闭包的
proxy
函数:
public static func createProxy(for object: AnyObject) -> Self {
return castOrFatalError(factory.createProxy(for: object))
}
public static func proxy(for object: ParentObject) -> Self {
MainScheduler.ensureRunningOnMainThread()
let maybeProxy = self.assignedProxy(for: object)
let proxy: AnyObject
if let existingProxy = maybeProxy {
proxy = existingProxy
}
else {
proxy = castOrFatalError(self.createProxy(for: object))
self.assignProxy(proxy, toObject: object)
assert(self.assignedProxy(for: object) === proxy)
}
let currentDelegate = self._currentDelegate(for: object)
let delegateProxy: Self = castOrFatalError(proxy)
if currentDelegate !== delegateProxy {
delegateProxy._setForwardToDelegate(currentDelegate, retainDelegate: false)
assert(delegateProxy._forwardToDelegate() === currentDelegate)
self._setCurrentDelegate(proxy, to: object)
assert(self._currentDelegate(for: object) === proxy)
assert(delegateProxy._forwardToDelegate() === currentDelegate)
}
return delegateProxy
}
代码分析:
- 首先使用
runtime
技术中的assignedProxy
函数获取关联属性,其实就是缓存的代理对象 - 如果没有值就执行
createProxy
函数,其实就是从DelegateProxyFactory
中取出注册的生成Rx代理对象的闭包执行,进而生成Rx代理对象 - 获取参数
ParentObject
的代理对象 - 如果代理对象和Rx代理对象不是同一个对象,那么将代理对象赋值给Rx代理对象的
forwardToDelegate
属性,将Rx代理对象作为参数ParentObject
真正的代理对象 - 返回Rx代理对象
总结
罗里吧嗦的分析这么久的代码,感觉调理不是很清楚,最后总结下,Rx
中代理的实现过程,就以UIScrollViewDelegate
协议的Rx
实现为例。
首先构建类RxScrollViewDelegateProxy
继承DelegateProxy
基类,同时遵守DelegateProxyType
、UIScrollViewDelegate
协议协议。在RxScrollViewDelegateProxy
中实现registerKnownImplementations
函数,为遵守UIScrollViewDelegate
协议的对象注册一个Rx
代理对象生成的闭包:
open class RxScrollViewDelegateProxy
: DelegateProxy<UIScrollView, UIScrollViewDelegate>
, DelegateProxyType
, UIScrollViewDelegate {
public init(scrollView: ParentObject) {
self.scrollView = scrollView
super.init(parentObject: scrollView, delegateProxy: RxScrollViewDelegateProxy.self)
}
public static func registerKnownImplementations() {
self.register { RxScrollViewDelegateProxy(scrollView: $0) }
self.register { RxTableViewDelegateProxy(tableView: $0) }
self.register { RxCollectionViewDelegateProxy(collectionView: $0) }
self.register { RxTextViewDelegateProxy(textView: $0) }
}
}
说明:此处的registerKnownImplementations
函数把UIScrollViewDelegate
协议的子协议的Rx代理对象的生成闭包一并注册了。
DelegateProxyType
协议定义的下面只读属性在DelegateProxyType
扩展中已经实现,所以不需要不实现:
extension DelegateProxyType { UnsafeRawPointer {
let delegateIdentifier = ObjectIdentifier(Delegate.self)
let integerIdentifier = Int(bitPattern: delegateIdentifier)
return UnsafeRawPointer(bitPattern: integerIdentifier)!
}
}
DelegateProxyType
协议定义的下面两个函数在DelegateProxyType
扩展中已经实现:
extension DelegateProxyType where ParentObject: HasDelegate, Self.Delegate == ParentObject.Delegate {
public static func currentDelegate(for object: ParentObject) -> Delegate? {
return object.delegate
}
public static func setCurrentDelegate(_ delegate: Delegate?, to object: ParentObject) {
object.delegate = delegate
}
}
上面DelegateProxyType
协议定义的两个函数虽然在DelegateProxyType
扩展中已经实现但是需要满足两个条件:
- 持有Rx代理对象的类必须遵守
HasDelegate
协议 -
Self.Delegate
的类型和持有Rx代理对象的类的Delegate
类型必须相同
所以扩展UIScrollView
类,让其准守HasDelegate
协议并且让Delegate
类型和Rx代理对象的类的Delegate
类型必须相同:
extension UIScrollView: HasDelegate {
public typealias Delegate = UIScrollViewDelegate
}
DelegateProxyType
协议定义的下面两个函数在Rx代理基类DelegateProxy
中已经实现,也不需要再实现了:
open func forwardToDelegate() -> Delegate? {
return castOptionalOrFatalError(self._forwardToDelegate)
}
open func setForwardToDelegate(_ delegate: Delegate?, retainDelegate: Bool) {
#if DEBUG // 4.0 all configurations
MainScheduler.ensureRunningOnMainThread()
#endif
self._setForwardToDelegate(delegate, retainDelegate: retainDelegate)
let sentSelectors: [Selector] = self._sentMessageForSelector.values.filter { $0.hasObservers }.map { $0.selector }
let invokedSelectors: [Selector] = self._methodInvokedForSelector.values.filter { $0.hasObservers }.map { $0.selector }
let allUsedSelectors = sentSelectors + invokedSelectors
for selector in Set(allUsedSelectors) {
self.checkSelectorIsObservable(selector)
}
self.reset()
}
协议函数的Observeble序列实现
有两种方法可以将协议中的函数实现为Observeble序列
Subject方式
这种方式需要在RxScrollViewDelegateProxy
类中,定义对应的UIScrollViewDelegate
协议中函数对应的Subject
,并且实现UIScrollViewDelegate
协议的函数,在协议的函数中调用Subject
的on
操作来发射元素:
private var _contentOffsetBehaviorSubject: BehaviorSubject<CGPoint>?
private var _contentOffsetPublishSubject: PublishSubject<()>?
internal var contentOffsetBehaviorSubject: BehaviorSubject<CGPoint> {
if let subject = _contentOffsetBehaviorSubject {
return subject
}
let subject = BehaviorSubject<CGPoint>(value: self.scrollView?.contentOffset ?? CGPoint.zero)
_contentOffsetBehaviorSubject = subject
return subject
}
internal var contentOffsetPublishSubject: PublishSubject<()> {
if let subject = _contentOffsetPublishSubject {
return subject
}
let subject = PublishSubject<()>()
_contentOffsetPublishSubject = subject
return subject
}
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let subject = _contentOffsetBehaviorSubject {
subject.on(.next(scrollView.contentOffset))
}
if let subject = _contentOffsetPublishSubject {
subject.on(.next(()))
}
self._forwardToDelegate?.scrollViewDidScroll?(scrollView)
}
deinit {
if let subject = _contentOffsetBehaviorSubject {
subject.on(.completed)
}
if let subject = _contentOffsetPublishSubject {
subject.on(.completed)
}
}
说明:开头就说了DelegateProxyType
协议允许使用正常的delegates
和Rx观察序列,因为RxScrollViewDelegateProxy.proxy(for: base)
中的proxy
操作会将正常的代理对象存储到Rx代理对象的forwardToDelegate
属性中,所以在协议函数的实现中调一下forwardToDelegate
对象的协议函数,达到对正常代理对象的支持(可以参看上面相应的代码分析)。
使用RxScrollViewDelegateProxy.proxy(for: base)
提供一个Rx代理对象,为了方便一般都是封装到一个Base
为UIScrollView
类的Reactive
扩展中,最后拿到相应的Subject
将其转化为Observeble
序列即可:
public var didScroll: ControlEvent<Void> {
let source = RxScrollViewDelegateProxy.proxy(for: base).contentOffsetPublishSubject
return ControlEvent(events: source)
}
消息转发方式
消息转发方式不需要实现UIScrollViewDelegate
协议中函数,因为没有实现,所以会走基类_RXDelegateProxy
的消息转发方法forwardInvocation:
(可参看前面相应的代码分析),主要做了如下三件事:
- 执行
_sentMessage:withArguments:
方法 - 将未知消息转发给
_forwardToDelegate
属性对象 - 执行
_methodInvoked:withArguments:
方法
_sentMessage:withArguments:
和_methodInvoked:withArguments:
方法在基类DelegateProxy
中都已实现(可以参看上面相应的代码分析),主要就是根据selector
获取相应的MessageDispatcher
(可以参看上面相应的代码分析)对象执行on
操作发射元素。将未知消息转发给_forwardToDelegate
属性对象是为了对正常代理对象的支持。
基类_RXDelegateProxy
暴露sentMessage
和methodInvoked
函数(可以参看上面相应的代码分析)根据selector
构建相应的MessageDispatcher
对象,并转化为Observeble
序列。
综上所述,所以直接执行Rx代理对象的sentMessage
和methodInvoked
函数就可以获得相应的Observeble
序列:
extension Reactive where Base: UIScrollView {
public var delegate: DelegateProxy<UIScrollView, UIScrollViewDelegate> {
return RxScrollViewDelegateProxy.proxy(for: base)
}
public var willBeginDecelerating: ControlEvent<Void> {
let source = delegate.methodInvoked(#selector(UIScrollViewDelegate.scrollViewWillBeginDecelerating(_:))).map { _ in }
return ControlEvent(events: source)
}
}