美文网首页
iOS 多播者:一对多模式封装

iOS 多播者:一对多模式封装

作者: 某非著名程序员 | 来源:发表于2021-02-05 22:10 被阅读0次

    描述:git仓库

    iOS delegate、block属于一对一的模式。
    有时候需要实现一对多的需求,通知可以实现。但有时候业务关联是很紧密的,通知的可读性不是很好。

    项目中目前使用的是GCDMulticastDelegate,发现其有几个缺点:

    1. GCDMulticastDelegate中都是在消息转发中进行消息调用,消息转发在iOS中代价比较高。
    2. 其消息调用都是异步提交到队列,导致堆栈信息无法跟踪。
    3. 库也比较老了,偶现闪退。体验不是很好。
    4. 使用起来不太方便,需要先定义multiDelegate,添加代理,不用需要移除,使用时还需要判断方法是否存在。
    @property(nonatomic, strong) GCDMulticastDelegate <BLEnterpriseManagerDelegate> *multiDelegate;
    
    - (instancetype)init {
        if (self = [super init]) {
            self.multiDelegate = (GCDMulticastDelegate <BLEnterpriseManagerDelegate> *) [[GCDMulticastDelegate alloc] init];
        }
        return self;
    }
    
    - (void)addDelegate:(id <BLEnterpriseManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)queue {
        [_multiDelegate addDelegate:delegate delegateQueue:queue];
    }
    
    - (void)removeDelegate:(id <BLEnterpriseManagerDelegate>)delegate {
        [_multiDelegate removeDelegate:delegate];
    }
    
    if ([self.multiDelegate hasDelegateThatRespondsToSelector:@selector(enterpriseManager:didClearAllOrgs:)]) {
        [self.multiDelegate enterpriseManager:self didClearAllOrgs:YES];
    }
    

    思考

    一对多就是观察者模式的使用,完全可以自己实现。

    1. 观察者使用封装在了NSObject扩展中,任何对象都可以添加观察者对象。不再需要在被观察者中声明什么。
    2. 消息调用使用了NSInvocation,不走消息转发。
    3. 如果不设置队列,默认都回到主线程;也可指定队列。
    4. 方法不存在,不需要外部判断。内部打印错误日志,注意观察。

    方案一

    使用

    1. 导入头文件
      #import "NSObject+BLObserver.h"
    2. 添加观察者
    [_customView wp_addObserver:self];
        
        _observer1 = [WPViewObserver new];
        _observer1.title = @"observer1 ";
        [_customView wp_addObserver:_observer1];
        
        _observer2 = [WPViewObserver new];
        _observer2.title = @"observer2 ";
        [_customView wp_addObserver:_observer2 delegateQueue:dispatch_queue_create("observer2", DISPATCH_QUEUE_SERIAL)];//指定队列
    
    1. 被观察者通知观察者:带参数调用
        [self wp_notifyObserverWithAction:@selector(update), nil];
        [self wp_notifyObserverWithAction:@selector(update:), 1,nil];
        [self wp_notifyObserverWithAction:@selector(update:count2:), 1,2,nil];
    
    1. 观察者监听
    - (void)update:(NSInteger)count{
        NSLog(@"detail update %ld",count);
    }
    
    - (void)update:(NSInteger)count count2:(NSInteger)count2{
        NSLog(@"detail update %ld,%ld",count,count2);
    }
    
    1. 退出页面后内存自动释放
    2021-02-06 23:18:16.655618+0800 WPObserver_Example[58471:640255] WPDetailViewController dealloc
    2021-02-06 23:18:16.656013+0800 WPObserver_Example[58471:640255] WPViewObserver dealloc observer2
    2021-02-06 23:18:16.656214+0800 WPObserver_Example[58471:640255] WPViewObserver dealloc observer1
    2021-02-06 23:18:16.656621+0800 WPObserver_Example[58471:640255] WPView dealloc
    

    小结

    1. 多数监听的或移除的时候都是在主线程,如果觉得线程不安全,也可以加个信号量。
    2. 观察者模式使用简单,要考虑到通用性,多参问题。
    3. 多参要考虑到int,double等基本类型。
    4. weak不持有观察者,不需要释放。只管监听,和通知观察者。如果有特殊情况,不需要监听了,可以调用[wp_removeObserver],移除监听;单例的监听者,需要手动移除。

    方案二

    以上方案可以实现通知,调用wp_notifyObserverWithAction:,不支持泛型。
    方案二去掉多参,加上线程安全,支持泛型。

    使用

    1. 添加观察者
    - (void)addObserver2{
        [_customView.proxyObserver addObserver:self];
        [_customView.proxyObserver addObserver:_observer1];
        [_customView.proxyObserver addObserver:_observer2 delegateQueue:dispatch_queue_create("observer2", DISPATCH_QUEUE_SERIAL)];//指定队列
    }
    
    1. 通知观察者,支持泛型
    [self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
        [target update];
    } selector:@selector(update)];
    
    [self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
        [target update:1];
    } selector:@selector(update:)];
    
    [self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
        [target update:1 count2:2];
    } selector:@selector(update:count2:)];
    
    [self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
        [target updateTitle:@"标题" count:4];
    } selector:@selector(updateTitle:count:)];
    

    相关文章

      网友评论

          本文标题:iOS 多播者:一对多模式封装

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