【iOS】如何實現Delegate鏈

CYMDelegateChain@github

實現delegate鏈/廣播前端

WHY

Delegate是IOS中普通使用的設計模式,一般只能指定一級delegate。但有的時候,好比使用UITableView,若是業務比較複雜,每一個section有獨立的數據和展現方式,很天然的就會想到把不一樣的section邏輯封裝成不一樣的類,這時你可能就會但願每一個section有本身的delegate。而CYMDelegateChain剛好能幫你作這些事。git

WHAT

CYMDelegateChain實現了delegate鏈,消息會在鏈上逐級傳遞,直到到達鏈表末尾,或者遇到實現了此消息的方法。默認狀況下,消息命中第一個方法後再也不向下傳遞,但能夠經過在被調用方法內執行CYMDelegateChainContinue(), 設置消息繼續向下傳遞。github

  • CYMDelegateChainInsert: 在鏈表前端插入delegate設計模式

//將section1插入列表前端
CYMDelegateChainInsert(self.dataSource, section1, self);
  • CYMDelegateChainRemove: 從鏈表中刪除已存在的delegate測試

//將section1從鏈表中刪除
CYMDelegateChainRemove(self.dataSource, section1, self);
  • CYMDelegateChainReplace: 從替換已存在的delegate
    //將section1從鏈表中刪除spa

//將section1替換section2
CYMDelegateChainReplace(self.dataSource, section1, section2, self);
  • CYMDelegateChainContinue: 設置continue標誌,指定當前delegate方法返回後,當前調用結束後,繼續調用下一個Delegate,能夠實現廣播設計

CYMDelegateChainContinue();

HOW

爲便於說明,舉一個簡單的例子:利用CYMDelegateChain,將UITableView的section邏輯獨立開來。
下面是關鍵部分的代碼,完整代碼請下載源碼查看。code

  1. 封裝類,處理section數據事件

    @interface TestTableViewSectionData : NSObject<UITableViewDataSource>
    @property NSInteger sectionId;
    @end
    
    @implementation TestTableViewSectionData
    - (UITableViewCell *)tableView:(UITableView *)tableView 
             cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        if (_sectionId == indexPath.section) { //只處理本section的消息
            //做一些與本section相關的事情
            ...
            return cell;
        }else{
            //非本section的消息,交給其餘delegate處理
            CYMDelegateChainContinue();
            return nil;
        }
    
    }
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        if (_sectionId == section) { //只處理本section的消息
            //做一些與本section相關的事情
            ...
        }else{
            //非本section的消息,交給其餘delegate處理
            CYMDelegateChainContinue();
            return 0;
        }
    }
    @end
  2. 封裝類,處理TableView數據,如section數量ci

    @interface TestTableViewData : NSObject<UITableViewDataSource>
    @property NSMutableArray* sections;
    @end
    
    @implementation TestTableViewData
    
    -(instancetype) init
    {
        self = [super init];
        if(self){
            _sections = [[NSMutableArray alloc]init];
        }
        return self;
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return _sections.count;
    }
    @end
  3. 擴展UITableView,方便對section的管理

    @implementation UITableView(TestSection)
    
    /** 添加section,返回sectionid */
    -(NSInteger) addTestSection:(TestTableViewSectionData*) section{
        
        TestTableViewData*data = objc_getAssociatedObject(self, @"__testdata");
        NSInteger sectionId = 0;
        if(!data){
            data = [[TestTableViewData alloc]init];
            objc_setAssociatedObject(self, @"__testdata", data, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
            //在鏈中插入新section,只處理numberOfSectionsInTableView
            CYMDelegateChainInsert(self.dataSource, data, self);
        }
        sectionId = data.sections.count;
        
        section.sectionId = sectionId;
        //在鏈中插入新section,每一個section只處理本身的事件
        CYMDelegateChainInsert(self.dataSource, section, self);
        
        [data.sections addObject:section];
        return sectionId;
    }
    @end
  4. 操做UITableView,插入多個section

    - (void)viewDidLoad {
        [super viewDidLoad];
        //測試section
        TestTableViewSectionData* sec0 = [[TestTableViewSectionData alloc]init];
        TestTableViewSectionData* sec1 = [[TestTableViewSectionData alloc]init];
        TestTableViewSectionData* sec2 = [[TestTableViewSectionData alloc]init];
        [_tabView addTestSection:sec0];
        [_tabView addTestSection:sec1];
        [_tabView addTestSection:sec2];
    }
  5. 查看運行結果
    demo.png?raw=true

相關文章
相關標籤/搜索