QTEventBus 源码心得

原理 : QTEventBus 将事件根据 key 保存到一个 array 中, 在发送事件时候, 查找map 中 key 对应的 array, 然后遍历 array调用事件

  1. 使用 block 实现链式编程, 这个在项目中用的很少, 需要熟练使用才可([QTEventBus shared]返回的是个QTEventBus 类型的对象, 然后调用[QTEventBus shared].on(NSObject) 返回一个 QTEventSubscriberMaker 类型的对象, 之后就开始了链式编程的路)
@interface QTEventBus<EventType> : NSObject
@property (class,readonly) QTEventBus * shared;
- (QTEventSubscriberMaker<EventType> *)on:(Class)eventClass;
 @end
  1. 在 QTEventSubscriberMaker 中使用泛型, 这样调用 next()时候, 会直接把传入的类返回回来
	// - 如果不使用泛型 
    [QTSub(self, DemoEvent) next:^(id event) {
        <#code#>
    }];
    // - 使用泛型
	 [QTSub(self, DemoEvent) next:^(DemoEvent *event) {
        <#code#>
    }];
    
// - 原因 : 
#define QTSub(_object_,_className_) ((QTEventSubscriberMaker <_className_ *> *)[_object_ subscribeSharedBus:[_className_ class]])
// - 1. 声明对象时候用到了 泛型
QTEventSubscriberMaker <_className_ *> *)
// - 2. 定义的 block 的参数使用了泛型的声明
typedef void (^QTEventNextBlock)(Value event) NS_SWIFT_UNAVAILABLE("");
// - 3. next 的参数是使用泛型的 block
- (id<QTEventToken>)next:(QTEventNextBlock)hander{
    return self.next(hander);
}
  1. 自动释放的原理(让A对象释放的时候, 释放掉bag, 即动态给A 对象添加一个eb_disposeBag属性, 当 A dealloc 时候, 会触发QTDisposeBag的 dealloc, 当 QTDisposeBag dealloc 时候, 会调用加入到 QTDisposeBag中的 tokens 中的所有对象, 然后调用每个对象的 dispose 方法)
@implementation NSObject (QTEventBus_Private)
- (QTDisposeBag *)eb_disposeBag{
    QTDisposeBag * bag = objc_getAssociatedObject(self, &event_bus_disposeContext);
    if (!bag) {
        bag = [[QTDisposeBag alloc] init];
        objc_setAssociatedObject(self, &event_bus_disposeContext, bag, OBJC_ASSOCIATION_RETAIN);
    }
    return bag;
}

@implementation QTDisposeBag
- (NSMutableArray<id<QTEventToken>> *)tokens{
    if (!_tokens) {
        _tokens = [[NSMutableArray alloc] init];
    }
    return _tokens;
}

- (void)addToken:(id<QTEventToken>)token{
    @synchronized(self) {
        [self.tokens addObject:token];
    }
}

- (void)dealloc{
    @synchronized(self) {
        for (id<QTEventToken> token in self.tokens) {
            if ([token respondsToSelector:@selector(dispose)]) {
                [token dispose];
            }
        }
    }
}
  1. 这里的很多对象都是随时添加, 删除,替换的, 如果使用数组, 效率比较低, 这里使用的链表, 在 OC 中的链表的设计
@interface QTEventBusCollection : NSObject
// - linkListTable 中有很多链表
@property (strong, nonatomic) NSMutableDictionary<NSString *,_QTEventBusLinkList *> * linkListTable;


@interface _QTEventBusLinkList: NSObject
// - 头结点
@property (strong, nonatomic) _QTEventBusLinkNode * head;
// - 尾节点
@property (strong, nonatomic) _QTEventBusLinkNode * tail;
// - 存储节点和 key 对应的键值对, 方便快速查找 节点
@property (strong, nonatomic) NSMutableDictionary * registeredNodeTable;

@interface _QTEventBusLinkNode: NSObject
// - 上一个节点
@property (weak, nonatomic) _QTEventBusLinkNode * previous;
// - 下一个节点
@property (weak, nonatomic) _QTEventBusLinkNode * next;

// - 删除的操作 :  需要通过 key 从 registeredNodeTable 中找到 node, 然后才可以链表中的某个 node 做删除的操作.
// - 插入的操作 : 需要通过 key 从 registeredNodeTable 中找到 某个相邻的node,  然后修改相邻节点和本 node的上一节点或下一节点, 实现插入操作
  1. 使用类别和宏定义
// - 1. 使用类别使每个对象都能轻易调到这个方法
[QTEventBus shared].on(xx) ----- 优化为 ---->   [self subscribeSharedBus:xx]

// - 2. 使用宏定义
    [(QTEventSubscriberMaker <DemoEvent *>*)[self subscribeSharedBus:[NSObject class]] next:^(DemoEvent *event) {
        NSLog(@"%ld",event.count);
    }];
------------ 优化为 ---------->
    [QTSub(self, DemoEvent) next:^(DemoEvent *event) {
        NSLog(@"%ld",event.count);
    }];

  1. 使用内联函数, 常用的且简单重复的代码封装在使用内联函数中
  2. 巧用协议
// -  _QTEventToken 和  _QTComposeToken 都遵守了  QTEventToken 协议, 而 QTEventToken 只有一个 - (void)dispose; 函数, 就是当 QTDisposeBag 释放时候, 调用每个 token 的释放, 而 _QTComposeToken 内部有个 NSArray<_QTEventToken *> * tokens; 当 _QTComposeToken dispose 时候, 就是遍历数组,调用每个元素的 dispose, 而每个 token 的 dispose 就是调用 token 的 @property (copy, nonatomic) void(^onDispose)(NSString * uniqueId); block
- (id<QTEventToken>)_createNewSubscriber:(QTEventSubscriberMaker *)maker{
    if (!maker.hander) {
        return nil;
    }
    if (maker.eventSubTypes.count == 0) {//一级事件
        _QTEventToken * token = [self _addSubscriberWithMaker:maker eventType:nil];
        return token;
    }
    NSMutableArray * tokens = [[NSMutableArray alloc] init];
    for (NSString * eventType in maker.eventSubTypes) {
        _QTEventToken * token = [self _addSubscriberWithMaker:maker eventType:eventType];
        [tokens addObject:token];
    }
    _QTComposeToken * token = [[_QTComposeToken alloc] initWithTokens:tokens];
    return token;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章