美文网首页
QMUI学习-QMUIMultipleDelegates

QMUI学习-QMUIMultipleDelegates

作者: 环宇飞杨 | 来源:发表于2020-05-13 10:50 被阅读0次

    功能介绍:

    用于解决项目中,代理只能指向一个对象的问题,在某些封装性高的类中,会使用self.delegate = self;来实现功能细节,但是给外部使用后就不能再监听到代理事件,代理在这种场景就会变得很难用。

    实现思路

    初步思路

    1. 继承宿主(UITextView),并增加delegates容器属性,用来储存需要监听的代理对象
    2. 将需要监听的对象,加入delegates容器
    3. 将宿主的delegate指向自身,每个代理事件内部都遍历delegates,通知事件到每个监听对象
    4. 宿主释放时,将delegates容器清空。

    优化

    1. delegates用NSPointArray,实现弱引用,避免对其它对象造成影响。

    缺点

    使用方式上需要使用[textView.delegates addObject:obj]; 的方式,无法做到无感知使用。

    QMUIMultipleDelegates

    类目介绍.png

    两个实现类,不到350行代码。

    NSObject+QMUIMultipleDelegates

    @interface NSObject (QMUIMultipleDelegates)
    
    /// 当你需要当前的 class 支持多个 delegate,请将此属性置为 YES。默认为 NO。
    @property(nonatomic, assign) BOOL qmui_multipleDelegatesEnabled;
    
    /// 让某个 delegate 属性也支持多 delegate 模式(默认只帮你加了 @selector(delegate) 的支持,如果有其他命名的 property 就需要自己用这个方法添加)
    - (void)qmui_registerDelegateSelector:(SEL)getter;
    
    /// 移除某个特定的 delegate 对象,例如假设你把 delegate 同时赋值给 objA 和 objB,而你只要移除 objB,则可:[self qmui_removeDelegate:objB]。但如果你想同时移除 objA 和 objB(也即全部 delegate),则像往常一样直接 self.delegate = nil 即可。
    - (void)qmui_removeDelegate:(id)delegate;
    
    @end
    

    为避免侵入性,使用了qmui_multipleDelegatesEnabled开关来控制模式开启,另外考虑delegate的命名各异,增加了- (void)qmui_registerDelegateSelector:(SEL)getter;方便用户主动注册代理,比如tableView的dateSource代理就需要主动注册,此处QMUI自动注册了@selector(delegate) ,所以就不需要手动再注册了。

    逻辑

    1. setQmui_multipleDelegatesEnabled 用于初始化一个字典容器,其中key为当前代理属性的变量名,value为QMUIMultipleDelegates对象,再往下看还会看到已经帮我们注册了delegate方法,并且如果是TableView或者CollectionView的话还会注册DataSource方法。
    2. 当执行self.delegate = obj 时,会用delegate为key寻找QMUIMultipleDelegates对象,如果对象不存在那么初始化QMUIMultipleDelegates对象,其内部是一个数组容器,此处先忽略,后续继续介绍。
      以下为字典容器的添加对象逻辑
        // 为这个 selector 创建一个 QMUIMultipleDelegates 容器
        NSString *delegateGetterKey = NSStringFromSelector(getter);//此处的getter就是self.delegate里的delegate。
        if (!self.qmuimd_delegates[delegateGetterKey]) { //字典容器未获取到value
            objc_property_t prop = class_getProperty(self.class, delegateGetterKey.UTF8String);
            QMUIPropertyDescriptor *property = [QMUIPropertyDescriptor descriptorWithProperty:prop];//获取属性详情(如:self.delegate)
            if (property.isStrong) { //如果self.delegate是强引用,那么创建一个强引用数组来保存对象。此处不知道应用场景,代理一般都写成weak形式的。
                // strong property
                QMUIMultipleDelegates *strongDelegates = [QMUIMultipleDelegates strongDelegates];
                strongDelegates.parentObject = self;
                self.qmuimd_delegates[delegateGetterKey] = strongDelegates;
            } else {
                // weak property
                QMUIMultipleDelegates *weakDelegates = [QMUIMultipleDelegates weakDelegates];
                weakDelegates.parentObject = self;
                self.qmuimd_delegates[delegateGetterKey] = weakDelegates;
            }
        }
    

    相关文章

      网友评论

          本文标题:QMUI学习-QMUIMultipleDelegates

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