IOS 实现delegate链/广播

CYMDelegateChain@github

An implement of delegate chain and broadcast. 实现delegate链/广播

WHY

Delegate是IOS中普通使用的设计模式,通常只能指定一级delegate。但有的时候,比如使用UITableView,如果业务比较复杂,每个section有独立的数据和展示方式,很自然的就会想到把不同的section逻辑封装成不同的类,这时你可能就会希望每个section有自己的delegate。而CYMDelegateChain恰好能帮你做这些事。

WHAT

CYMDelegateChain实现了delegate链,消息会在链上逐级传递,直到到达链表末尾,或者遇到实现了此消息的方法。默认情况下,消息命中第一个方法后不再向下传递,但可以通过在被调用方法内执行CYMDelegateChainContinue(), 设置消息继续向下传递。

  • CYMDelegateChainInsert: 在链表前端插入delegate
//将section1插入列表前端
CYMDelegateChainInsert(self.dataSource, section1, self);
  • CYMDelegateChainRemove: 从链表中删除已存在的delegate
//将section1从链表中删除
CYMDelegateChainRemove(self.dataSource, section1, self);
  • CYMDelegateChainReplace: 从替换已存在的delegate
    //将section1从链表中删除
//将section1替换section2
CYMDelegateChainReplace(self.dataSource, section1, section2, self);
  • CYMDelegateChainContinue: 设置continue标志,指定当前delegate方法返回后,当前调用结束后,继续调用下一个Delegate,可以实现广播
CYMDelegateChainContinue();

HOW

为便于说明,举一个简单的例子:利用CYMDelegateChain,将UITableView的section逻辑独立开来。
下面是关键部分的代码,完整代码请下载源码查看。

  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数量

    @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. 运行查看效果
    这里写图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在iOS开发中,可以使用Block和delegate实现一对多的回调。使用delegate时,首先需要定义一个delegate协议,其中包含回调方法。然后在需要进行回调的地方,设置delegate并调用回调方法。具体实现可以参考以下代码示例:\[2\] ``` // 定义delegate协议 protocol FirstCellDelegate: class { func firstCellBtnTap(_ cell: firstTableViewCell) } // 在需要进行回调的地方设置delegate并调用回调方法 weak var delegate: FirstCellDelegate? // 调用回调方法 if let delegate = self.delegate { delegate.firstCellBtnTap(self) } // 实现delegate回调方法 func firstCellBtnTap(_ cell: firstTableViewCell) { let cellIndexPath = tableView.indexPath(for: cell) print("delegate回调 section:\(cellIndexPath?.section ?? 0), row:\(cellIndexPath?.row ?? 0)") } ``` 另外,使用Block也可以实现一对多的回调。Block可以作为函数表达式传递给API,可以选择性地存储,并且可以被多个线程使用。Block不仅包含了在回调时需要执行的代码,还包含了执行期间所需的数据。具体实现可以参考以下代码示例:\[3\] ``` // 定义Block回调 typealias CallbackBlock = () -> Void // 在需要进行回调的地方使用Block进行回调 var callback: CallbackBlock? // 调用回调 callback?() ``` 通过使用Block和delegate,可以实现一对多的回调,满足不同场景下的需求。 #### 引用[.reference_title] - *1* [Block实现iOS回调](https://blog.csdn.net/feelinghappy/article/details/119870367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [iOS Block与Delegate的用法,各自优缺点及使用场景](https://blog.csdn.net/huangshanfeng/article/details/82106580)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值