以擴展CLLocationManager和MKMapView為例,探索DelegateProxy的底層實現(xiàn)
Extension CLLocationManager
Question:
1. 怎樣為CLLocationManager的實例添加rx名稱空間扳碍?
2. 為CLLocationManager的實例的rx名稱空間里定義可觀察存儲屬性
3. 這個可觀察存儲屬性如何獲取CLLocationManager的delegate接收到的數(shù)據(jù)并發(fā)起事件給訂閱者桑阶?
4. DelegateProxy的作用是什么欲间?
5. DelegateProxy如何代理CLLocationManager的delegate接收到的數(shù)據(jù)继阻?
1.怎樣為CLLocationManager添加rx名稱空間
// 定義在RxSwift中的Reactive.swift文件中
public struct Reactive<Base> {
/// Base object to extend.
public let base: Base
/// Creates extensions with base object.
///
/// - parameter base: Base object.
public init(_ base: Base) {
self.base = base
}
}
public protocol ReactiveCompatible {
/// Extended type
associatedtype ReactiveBase
@available(*, deprecated, renamed: "ReactiveBase")
typealias CompatibleType = ReactiveBase
/// Reactive extensions.
static var rx: Reactive<ReactiveBase>.Type { get set }
/// Reactive extensions.
var rx: Reactive<ReactiveBase> { get set }
}
extension ReactiveCompatible {
/// Reactive extensions.
public static var rx: Reactive<Self>.Type {
get {
return Reactive<Self>.self
}
// swiftlint:disable:next unused_setter_value
set {
// this enables using Reactive to "mutate" base type
}
}
/// Reactive extensions.
public var rx: Reactive<Self> {
get {
return Reactive(self)
}
// swiftlint:disable:next unused_setter_value
set {
// this enables using Reactive to "mutate" base object
}
}
}
extension NSObject: ReactiveCompatible { }
// 擴展Reactive, 為CLLocationManager添加rx名稱空間
public extension Reactive where Base: CLLocationManager {}
2. 為rx添加可觀察的存儲屬性
public extension Reactive where Base: CLLocationManager {
var didUpdateLocations: Observable<[CLLocation]> {
}
}
3. 當CLLocationManager的代理接收到數(shù)據(jù)時髓考,可觀察對象發(fā)起事件給訂閱者
public extension Reactive where Base: CLLocationManager {
var delegate: DelegateProxy<CLLocationManager, CLLocationManagerDelegate> {
RxCLLocationManagerDelegateProxy.proxy(for: base)
}
var didUpdateLocations: Observable<[CLLocation]> {
delegate
.methodInvoked(
#selector(CLLocationManagerDelegate.locationManager(_:didUpdateLocations:))
)
.map { parameters in
parameters[1] as! [CLLocation]
}
}
}
4. DelegateProxy是什么
The DelegateProxy object creates a fake delegate object, which will proxy all the data received into dedicated observables
定義委托代理RxCLLocationManagerDelegateProxy, 代理接收到的數(shù)據(jù)給可觀察序列
RxCLLocationManagerDelegateProxy
class RxCLLocationManagerDelegateProxy: DelegateProxy<CLLocationManager, CLLocationManagerDelegate>, DelegateProxyType, CLLocationManagerDelegate {
weak public private(set) var locationManager: CLLocationManager?
public init(locationManager: ParentObject) {
self.locationManager = locationManager
super.init(parentObject: locationManager, delegateProxy: RxCLLocationManagerDelegateProxy.self)
}
static func registerKnownImplementations() {
register {
RxCLLocationManagerDelegateProxy(locationManager: $0)
}
}
}
5. DelegateProxy如何代理CLLocationManager的delegate接收到的數(shù)據(jù)
-
RxCLLocationManagerDelegateProxy實例的創(chuàng)建過程
let locationManager = CLLocationManager.init() locationManager.rx.delegate即為RxCLLocationManagerDelegateProxy的實例 // DelegateProxyType.swift // 通過存儲屬性delegate的get方法, 該委托代理的實例化是通過RxCLLocationManagerDelegateProxy.proxy(for: base)實現(xiàn)的 // 1. RxCLLocationManagerDelegateProxy的實例是作為CLLocationManager實例的關聯(lián)屬性保存的 // 2. ParentObject為CLLocationManager的實例對象 public static func proxy(for object: ParentObject) -> Self { // 1. 獲取CLLocationManager實例對象標識為self.identifier的關聯(lián)屬性 let maybeProxy = self.assignedProxy(for: object) let proxy: AnyObject if let existingProxy = maybeProxy { // 2. 如果該關聯(lián)屬性存在, 則返回該關聯(lián)屬性 proxy = existingProxy } else { // 3. 如果該關聯(lián)屬性不存在, 則創(chuàng)建該實例 proxy = castOrFatalError(self.createProxy(for: object)) // 4. 保存為CLLocationManager實例的關聯(lián)屬性 self.assignProxy(proxy, toObject: object) } let currentDelegate = self._currentDelegate(for: object) let delegateProxy: Self = castOrFatalError(proxy) return delegateProxy }
-
創(chuàng)建RxCLLocationManagerDelegateProxy的實例
// DelegateProxyType.swift // object為CLLocationManager的實例對象 public static func createProxy(for object: AnyObject) -> Self { return castOrFatalError(factory.createProxy(for: object)) }
-
factory是什么
// DelegateProxyType.swift extension DelegateProxyType { // 1. factory是DelegateProxyType擴展的靜態(tài)存儲屬性 private static var factory: DelegateProxyFactory { // self為RxCLLocationManagerDelegateProxy類對象, 它遵守DelegateProxyType協(xié)議 return DelegateProxyFactory.sharedFactory(for: self) } } // 這里使用了工廠模式, _sharedFactories里保存了各DelegateProxyType類所對應的工廠實例DelegateProxyType private class DelegateProxyFactory { private static var _sharedFactories: [UnsafeRawPointer: DelegateProxyFactory] = [:] // proxyType為RxCLLocationManagerDelegateProxy類對象 fileprivate static func sharedFactory<DelegateProxy: DelegateProxyType>(for proxyType: DelegateProxy.Type) -> DelegateProxyFactory { // 泛型DelegateProxy即為RxCLLocationManagerDelegateProxy let identifier = DelegateProxy.identifier if let factory = _sharedFactories[identifier] { return factory } let factory = DelegateProxyFactory(for: proxyType) _sharedFactories[identifier] = factory // 保存DelegateProxy的子類到factory DelegateProxy.registerKnownImplementations() return factory } }
-
registerKnownImplementations
-
作用
注冊子類RxCLLocationManagerDelegateProxy的實例化閉包
-
調(diào)用鏈路
private class DelegateProxyFactory { fileprivate static func sharedFactory<DelegateProxy: DelegateProxyType>(for proxyType: DelegateProxy.Type) -> DelegateProxyFactory { ... DelegateProxy.registerKnownImplementations() ... } }
class RxCLLocationManagerDelegateProxy: DelegateProxy<CLLocationManager, CLLocationManagerDelegate>, DelegateProxyType, CLLocationManagerDelegate { static func registerKnownImplementations() { register { RxCLLocationManagerDelegateProxy(locationManager: $0) } } }
extension DelegateProxyType { // Parent的類型是CLLocationManager public static func register<Parent>(make: @escaping (Parent) -> Self) { self.factory.extend(make: make) } }
// ParentObject的類型是CLLocationManager, 閉包的返回類型是DelegateProxy的子類RxCLLocationManagerDelegateProxy func extend<DelegateProxy: DelegateProxyType, ParentObject>(make: @escaping (ParentObject) -> DelegateProxy) { ... // 這里factory的key是類對象CLLocationManager的identifier self._factories[ObjectIdentifier(ParentObject.self)] = {make(castOrFatalError($0)) } ... }
-
通過以上調(diào)用,DelegateProxyFactory的實例在調(diào)用createProxy方法時舞痰,就能獲取到相應的閉包土榴,返回閉包所創(chuàng)建的實例對象RxCLLocationManagerDelegateProxy
-
-
工廠DelegateProxyFactory如何創(chuàng)建RxCLLocationManagerDelegateProxy實例
private class DelegateProxyFactory { // object為CLLocationManager的實例對象 fileprivate func createProxy(for object: AnyObject) -> AnyObject { var maybeMirror: Mirror? = Mirror(reflecting: object) while let mirror = maybeMirror { // 獲取注冊過的閉包 if let factory = self._factories[ObjectIdentifier(mirror.subjectType)] { // 調(diào)用該閉包返回RxCLLocationManagerDelegateProxy的實例化對象 return factory(object) } maybeMirror = mirror.superclassMirror } } }
-
-
RxCLLocationManagerDelegateProxy實例成為CLLocationManager對象的代理
public static func proxy(for object: ParentObject) -> Self { ... self._setCurrentDelegate(proxy, to: object) ... } extension DelegateProxyType where ParentObject: HasDelegate, Self.Delegate == ParentObject.Delegate { public static func setCurrentDelegate(_ delegate: Delegate?, to object: ParentObject) { object.delegate = delegate } }
-
生成可觀察序列
open class DelegateProxy<P: AnyObject, D>: _RXDelegateProxy { open func methodInvoked(_ selector: Selector) -> Observable<[Any]> { // 每個selector對應一個MessageDispatcher實例 let subject = self._methodInvokedForSelector[selector] if let subject = subject { // _methodInvokedForSelector中存在 return subject.asObservable() } else { // 不存在, 則實例化對應的MessageDispatcher實例并保存 let subject = MessageDispatcher(selector: selector, delegateProxy: self) self._methodInvokedForSelector[selector] = subject return subject.asObservable() } } }
-
通過消息轉發(fā)機制,轉發(fā)對應的代理方法所獲取到的數(shù)據(jù)
由于在實例化RxCLLocationManagerDelegateProxy的過程中响牛,已經(jīng)將RxCLLocationManagerDelegateProxy的實例作為CLLocationManager對象的delegate玷禽,但是并沒有提供對應代理方法的實現(xiàn),所有底層在通過代理調(diào)用相應的代理方法時呀打,會因為找不到對應的方法實現(xiàn)而進行消息轉發(fā)
- 委托代理的繼承體系
RxCLLocationManagerDelegateProxy:DelegateProxy:_RXDelegateProxy open class DelegateProxy<P: AnyObject, D>: _RXDelegateProxy {}
@interface _RXDelegateProxy : NSObject @end @implementation _RXDelegateProxy @end
- 生成事件轉發(fā)給訂閱者
@implementation _RXDelegateProxy -(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]; } } @end
open class DelegateProxy<P: AnyObject, D>: _RXDelegateProxy { open override func _sentMessage(_ selector: Selector, withArguments arguments: [Any]) { // 獲取可觀察序列, 發(fā)送事件給訂閱者 self._sentMessageForSelector[selector]?.on(.next(arguments)) } open override func _methodInvoked(_ selector: Selector, withArguments arguments: [Any]) { // 獲取可觀察序列, 發(fā)送事件給訂閱者 self._methodInvokedForSelector[selector]?.on(.next(arguments)) } }
Extension a UIKit view
MKMapView, for example
Question:
1. 為什么在Rx中包裝一個具有返回類型的委托是一件困難的事情矢赁?
2. 怎樣處理帶有返回值的代理方法?
1. 為什么在Rx中包裝一個具有返回類型的委托是一件困難的事情贬丛?
- 帶有返回類型的委托方法并不用于觀察撩银,而是用于自定義行為
- 定義一個在任何情況下都可以工作的自動默認值不是一項簡單的任務
2. 怎樣處理帶有返回值的代理方法?
轉發(fā)帶有返回值的委托方法調(diào)用
public extension Reactive where Base: MKMapView {
var delegate: DelegateProxy<MKMapView, MKMapViewDelegate> {
RxMKMapViewDelegateProxy.proxy(for: base)
}
// 轉發(fā)帶有返回值的委托方法調(diào)用給MKMapView
func setDelegate(_ delegate: MKMapViewDelegate) -> Disposable {
RxMKMapViewDelegateProxy.installForwardDelegate(delegate, retainDelegate: false, onProxyForObject: self.base)
}
var overlay:Binder<MKOverlay> {
Binder(base) { mapView, overlay in
mapView.removeOverlays(mapView.overlays)
mapView.addOverlay(overlay)
}
}
}
// 上層以傳統(tǒng)方式遵守MKMapViewDelegate協(xié)議并實現(xiàn)其帶有返回值的委托方法
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView,
rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let overlay = overlay as? ApiController.Weather.Overlay else {
return MKOverlayRenderer()
}
return ApiController.Weather.OverlayView(overlay: overlay,
overlayIcon: overlay.icon)
}
}
轉發(fā)過程的底層實現(xiàn)
調(diào)用鏈路
public extension Reactive where Base: MKMapView {
func setDelegate(_ delegate: MKMapViewDelegate) -> Disposable {
RxMKMapViewDelegateProxy.installForwardDelegate(delegate, retainDelegate: false, onProxyForObject: self.base)
}
}
extension DelegateProxyType {
// forwardDelegate為遵守MKMapViewDelegate協(xié)議并提供相應委托方法實現(xiàn)的對象豺憔,即上層的ViewController實例對象
// ParentObject為MKMapView的實例
public static func installForwardDelegate(_ forwardDelegate: Delegate, retainDelegate: Bool, onProxyForObject object: ParentObject) -> Disposable {
weak var weakForwardDelegate: AnyObject? = forwardDelegate as AnyObject
// proxy為委托代理對象额获,即RxMKMapViewDelegateProxy的實例
let proxy = self.proxy(for: object)
proxy.setForwardToDelegate(forwardDelegate, retainDelegate: retainDelegate)
...
}
}
open func setForwardToDelegate(_ delegate: Delegate?, retainDelegate: Bool) {
self._setForwardToDelegate(delegate, retainDelegate: retainDelegate)
}
@interface _RXDelegateProxy () {}
@implementation _RXDelegateProxy {
// forwardToDelegate為遵守MKMapViewDelegate協(xié)議并提供相應委托方法實現(xiàn)的對象够庙,即上層的ViewController實例對象
-(void)_setForwardToDelegate:(id __nullable)forwardToDelegate retainDelegate:(BOOL)retainDelegate {
__forwardToDelegate = forwardToDelegate;
if (retainDelegate) {
self.strongForwardDelegate = forwardToDelegate;
} else {
self.strongForwardDelegate = nil;
}
}
}
- 生成事件轉發(fā)給訂閱者
@implementation _RXDelegateProxy
-(void)forwardInvocation:(NSInvocation *)anInvocation {
...
if (self._forwardToDelegate && [self._forwardToDelegate respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:self._forwardToDelegate];
}
...
}
@end