无需移除的KVOApi-iOS,一行代码block回调

2021-09-28  本文已影响0人  不拘小节123456

新版kvoblock回调虽然不需要移除操作,但是需要增加很多成员变量,通过关联对象技术,给监听对象动态添加了一个map来持有这些对象

KCKVOObserverProtocol实现改协议
//调用api
addKVOObserver(target: btn, keyPath: "frame", option: [.new,.old]) { (change) in
            print("change -----\(change)")
        }

//具体实现

//
//  KVO+Tool.swift
//  KCNotificationCenterTool
//
//  Created by FanQiLe on 2021/9/28.
//

import UIKit

private var kvoTokensKey = "KCKVOObserverProtocol"
public protocol KCKVOObserverProtocol: NSObjectProtocol {}

public typealias KVOBlock = (([NSKeyValueChangeKey : Any]) -> ())
class KCKVOItemObj: NSObject {
    var block:KVOBlock?
    var target:NSObject?
    var keyPath: String?
    class func createOBj(target:NSObject,keyPath:String,option:NSKeyValueObservingOptions,block:KVOBlock?) -> KCKVOItemObj {
        let temp = KCKVOItemObj()
        temp.target = target
        temp.keyPath = keyPath
        temp.block = block
        target.addObserver(temp, forKeyPath: keyPath, options: option, context: nil)
        return temp
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        self.block?(change ?? [:])
    }
    deinit {
        self.target?.removeObserver(self, forKeyPath: self.keyPath ?? "")
    }
}

extension KCKVOObserverProtocol {
    public func addKVOObserver(target:NSObject,keyPath:String,option:NSKeyValueObservingOptions,block:KVOBlock?) {
        var tokens = getTokens()
        let obj = KCKVOItemObj.createOBj(target: target, keyPath: keyPath, option: option, block: block)
        let objStr = String(describing: target.self)
        tokens["\(objStr)\(keyPath)"] = obj;
        setTokens(tokens)
    }

        
    private func getTokens() -> [String: KCKVOItemObj] {
        synchronized(self) {
            if let observers = objc_getAssociatedObject(self, &kvoTokensKey) as? [String: KCKVOItemObj] {
                return observers
            }
            return [String: KCKVOItemObj]()
        }
    }
    
    private func setTokens(_ tokens: [String: KCKVOItemObj]) {
        synchronized(self) {
            objc_setAssociatedObject(self, &kvoTokensKey, tokens, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

demo请看下面
https://github.com/riceForChina/NotificationCenter-Tool.git

上一篇下一篇

猜你喜欢

热点阅读