ReactorKit 中定义了 Reactor 协议,同时对 Reactor 协议进行了扩展。一个类型经过继承 Reactor 协议,就得到了下面几个属性:api
如何经过协议进行扩展,来给继承者添加实例变量呢?bash
// MARK: - Map Tables
private typealias AnyReactor = AnyObject
private enum MapTables {
static let action = WeakMapTable<AnyReactor, AnyObject>()
static let currentState = WeakMapTable<AnyReactor, Any>()
static let state = WeakMapTable<AnyReactor, AnyObject>()
static let disposeBag = WeakMapTable<AnyReactor, DisposeBag>()
static let isStubEnabled = WeakMapTable<AnyReactor, Bool>()
static let stub = WeakMapTable<AnyReactor, AnyObject>()
}
复制代码
经过源码查看,能够发现有一个 MapTables 的枚举类型,里面定义了几个静态常量(static let),每一个静态常量都对应了一个扩展的属性,好比 action 静态变量就是为了给继承 Reactor 协议的类型添加 action 属性。ui
在 MapTables 中的静态常量的类型为 WeakMapTable。其中,定义了一个 dictionary,将类和扩展得来的属性值进行对应,这样就能够记录每一个类对应的扩展的属性值。spa
WeakMapTable 管理的 dictionary 须要知足下面的条件:code
下面来看一下 WeakMapTable 是怎么管理 dictionary 的。dictionary 的 key 的类型是 Weak。一个 Weak 实例对别扩展的类进行了弱引用,并保存了类实例的惟一标识的哈希值。继承
// MARK: - Weak
private class Weak<T>: Hashable where T: AnyObject {
private let objectHashValue: Int
weak var object: T?
init(_ object: T) {
// 类实例的惟一标志
self.objectHashValue = ObjectIdentifier(object).hashValue
self.object = object
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.objectHashValue)
}
static func == (lhs: Weak<T>, rhs: Weak<T>) -> Bool {
return lhs.objectHashValue == rhs.objectHashValue
}
}
复制代码
这样就知足了条件 1 和条件 2。ci
在设置 dictionary 中 key 对应的被扩展的属性值时的方法以下:rem
func setValue(_ value: Value?, forKey key: Key) {
let weakKey = Weak(key)
self.lock.lock()
defer {
self.lock.unlock()
if value != nil {
self.installDeallocHook(to: key)
}
}
if let value = value {
self.dictionary[weakKey] = value
} else {
self.dictionary.removeValue(forKey: weakKey)
}
}
复制代码
其中调用了 installDeallocHook
方法,其中的参数为被扩展的类,installDeallocHook
的实现以下:get
// MARK: Dealloc Hook
private var deallocHookKey: Void?
private func installDeallocHook(to key: Key) {
let isInstalled = (objc_getAssociatedObject(key, &deallocHookKey) != nil)
guard !isInstalled else { return }
let weakKey = Weak(key)
let hook = DeallocHook(handler: { [weak self] in
self?.lock.lock()
self?.dictionary.removeValue(forKey: weakKey)
self?.lock.unlock()
})
objc_setAssociatedObject(key, &deallocHookKey, hook, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
复制代码
installDeallocHook 方法就是将被扩展的实例关联了一个 DeallocHook 实例变量。DeallocHook 初始化的 handler 是将 Dictionary 中被扩展的实例对应的 key 进行了删除。源码
DeallocHook 的定义以下:
// MARK: - DeallocHook
private class DeallocHook {
private let handler: () -> Void
init(handler: @escaping () -> Void) {
self.handler = handler
}
deinit {
self.handler()
}
}
复制代码
DeallocHook 实例做为被扩展的实例的属性。被扩展的实例在销毁时,DeallocHook 天然也会销毁,这时就会调用 handler。这样就保证的条件 3。
WeakMapTable 经过下面的方式来对实例扩展实例变量属性: