美文网首页
无需移除的KVOApi-iOS,一行代码block回调

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

作者: 不拘小节123456 | 来源:发表于2021-09-28 15:46 被阅读0次

    新版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

    相关文章

      网友评论

          本文标题:无需移除的KVOApi-iOS,一行代码block回调

          本文链接:https://www.haomeiwen.com/subject/dohrnltx.html