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;
}

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