QTEventBusソースコードの心得


QTEventBusは、イベントをkeyに従ってarrayに保存し、イベントを送信するときにmapのkeyに対応するarrayを検索し、array呼び出しイベントを巡回します.
  • はblockを用いてチェーンプログラミングを実現するが、これはプロジェクトではあまり使われておらず、熟練して使用する必要がある([QTEventBus shared]QTEventBusタイプのオブジェクトを返し、[QTEventBus shared].on(NSObject)を呼び出してQTEventSubscriberMakerタイプのオブジェクトを返し、その後チェーンプログラミングの道を開始する)
  • @interface QTEventBus : NSObject
    @property (class,readonly) QTEventBus * shared;
    - (QTEventSubscriberMaker *)on:(Class)eventClass;
     @end
    
  • QTEventSubscriberMakerで汎用を使用するとnext()が呼び出されると、直接入力されたクラスが
  • に戻る.
    	// -         
        [QTSub(self, DemoEvent) next:^(id event) {
            
        }];
        // -     
    	 [QTSub(self, DemoEvent) next:^(DemoEvent *event) {
            
        }];
        
    // -    : 
    #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)next:(QTEventNextBlock)hander{
        return self.next(hander);
    }
    
  • 自動解放の原理(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> *)tokens{
        if (!_tokens) {
            _tokens = [[NSMutableArray alloc] init];
        }
        return _tokens;
    }
    
    - (void)addToken:(id)token{
        @synchronized(self) {
            [self.tokens addObject:token];
        }
    }
    
    - (void)dealloc{
        @synchronized(self) {
            for (id token in self.tokens) {
                if ([token respondsToSelector:@selector(dispose)]) {
                    [token dispose];
                }
            }
        }
    }
    
  • ここの多くのオブジェクトは随時追加、削除、置換され、配列を使用すると効率が低く、ここで使用するチェーンテーブル、OCでのチェーンテーブルの設計
  • @interface QTEventBusCollection : NSObject
    // - linkListTable       
    @property (strong, nonatomic) NSMutableDictionary * 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.                    
    [QTEventBus shared].on(xx) -----     ---->   [self subscribeSharedBus:xx]
    
    // - 2.      
        [(QTEventSubscriberMaker *)[self subscribeSharedBus:[NSObject class]] next:^(DemoEvent *event) {
            NSLog(@"%ld",event.count);
        }];
    ------------     ---------->
        [QTSub(self, DemoEvent) next:^(DemoEvent *event) {
            NSLog(@"%ld",event.count);
        }];
    
    
  • はインライン関数を使用する、一般的かつ単純に繰り返されるコードは、インライン関数を使用する
  • にカプセル化される.
  • 巧用プロトコル
  • // -  _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)_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;
    }