OC 链式编程第二部分 - 调用篇

1. UITableView的常规调用

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    MyStoreCell *cell=[tableView dequeueReusableCellWithIdentifier:@"storeCell"];
    return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 90.0;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}
//移除
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {  
    } 
}

上面就是我们常规使用tableView的代码。在每次使用tableView的时候,我们都要写一大堆重复代理方法,不仅写着很烦,而且它如果放在控制器,让原本就臃肿的控制器便的更加臃肿。我们写代码的原则就是尽量避免重复的代码,那么是不是要想办法将这些代理方法抽取一下。怎么抽取呢?答案是block代替代理方法。我们知道block底层是函数,那么是oc的方法,我们就可以用block去取代它。再结合我的上篇文章OC 链式编程第一部分 - UI创建篇,也就是链式编程的思想,由此衍生出本篇文章链式调用tableView和collectionView。

本篇文章代码https://github.com/zfc769956454/ChainedDemo(下载下来运行ChainedDemo链式调用TableView和CollectionView这个target)

image.png

2. tableView的链式调用和分析

2.1 tableView的链式调用

这里我们先看看调用效果,代码如下:

    __weak typeof(self)weakSelf = self;
    [self.tableView configure:^(ZFC_TableViewChainedInvokeCreater *creater) {
        creater.zfc_tableViewConfigure(tableViewConfig)
        .zfc_numberOfSectionsInTableView(^NSInteger(UITableView *tableView){
            return 3;
        })
        .zfc_numberOfRowsInSection(^NSInteger(UITableView *tableView,NSInteger section) {
            return weakSelf.dataSource.count;
        })
        .zfc_heightForRowAtIndexPath(^CGFloat(UITableView *tableView,NSIndexPath *indexPath) {
            return 50;
        })
        .zfc_cellForRowAtIndexPath(^(UITableView *tableView,__kindof ZFC_TableViewCell *cell, NSIndexPath *indexPath) {
            cell.myLabel.text = [NSString stringWithFormat:@"%@%@",weakSelf.dataSource[indexPath.row],isXIB?@"->XIB":@""];
            cell.contentView.backgroundColor = [UIColor grayColor];
        })
        .zfc_heightForHeaderInSection(^CGFloat(UITableView *tableView,NSInteger section) {
            return 40;
        })
        .zfc_viewForHeaderInSection(^(UITableView *tableView,__kindof ZFC_TableViewHeaderFooterView *headerView,NSInteger section) {
            headerView.myLabel.text = [NSString stringWithFormat:@"我是第-- %ld --段头%@",section,isXIB?@"->XIB":@""];
            headerView.contentView.backgroundColor = [UIColor yellowColor];
        })
        .zfc_heightForFooterInSection(^CGFloat(UITableView *tableView,NSInteger section) {
            return 40;
        }).zfc_viewForFooterInSection(^(UITableView *tableView,__kindof ZFC_TableViewHeaderFooterView *footerView,NSInteger section) {
            footerView.myLabel.text = [NSString stringWithFormat:@"我是第-- %ld --段尾%@",section,isXIB?@"->XIB":@""];
            footerView.contentView.backgroundColor = [UIColor blueColor];
        })
        .zfc_deleteCellWithIndexPath(^(UITableView *tableView, NSIndexPath *indexPath) {
            NSLog(@"删除");
            [weakSelf.dataSource removeLastObject];
            [tableView reloadData];
        })
        .zfc_didSelectRowAtIndexPath(^(UITableView *tableView,NSIndexPath *indexPath) {
            NSLog(@"我点击了%@",weakSelf.dataSource[indexPath.row]);
        });
    }];

这样看起来是不是很爽,tableView的常用的代理方法一股气的.下去,看起来不仅美观,而且我们不用再每个用到tableView的地方去遵守协议方法、设置代理、写代理方法了。

2.2 核心部分分析

这里我就以第一个链式调用zfc_numberOfSectionsInTableView来分析,其它的思路都相似,先上这段代码的实现
(1)在ZFC_TableViewChainedInvokeCreater这个类中定义属性

/**
 返回section数量
 */
typedef ZFC_TableViewChainedInvokeCreater *(^ZFC_numberOfSectionsInTableView)(NSInteger(^)(UITableView *tableView));
/** section数量 */
@property (nonatomic,readonly) ZFC_numberOfSectionsInTableView zfc_numberOfSectionsInTableView;

(2)在ZFC_TableViewChainedInvokeCreater.m中申明一个属性block->numberOfSectionsInTableViewHandle用来保存外界传来的section调用的block,也就是zfc_numberOfSectionsInTableView(A)的参数

/** section数量--保存用的block */
@property (nonatomic,copy)NSInteger (^numberOfSectionsInTableViewHandle)(UITableView *tableView) ;
//重写getter方法
- (ZFC_numberOfSectionsInTableView)zfc_numberOfSectionsInTableView {
    return ^ZFC_TableViewChainedInvokeCreater *(NSInteger (^sectionsHandle)(UITableView *tableView)) { 
        self.numberOfSectionsInTableViewHandle =  sectionsHandle;
        return self;
    };  
}

(3)在tableView返回section的代理方法中执行(2)中保存的block->numberOfSectionsInTableViewHandle

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if(self.numberOfSectionsInTableViewHandle) return self.numberOfSectionsInTableViewHandle(tableView);
    return 0;
}

(4)下面我们来看一下执行过程
第一步:调用zfc_numberOfSectionsInTableView(实参A),此处实参A是一个block,如下

//实参A
^NSInteger(UITableView *tableView){
          return 3;
 }

第二步:在ZFC_TableViewChainedInvokeCreater.m中重写了get方法,它的返回值是一个block->也就是zfc_numberOfSectionsInTableView,zfc_numberOfSectionsInTableView的参数是一个block->也就是上面的实参A,在这个getter方法中,用一个block->numberOfSectionsInTableViewHandle来保存这个实参
第三步:在tableView的代理方法中执行上一步保存numberOfSectionsInTableViewHandle->也就是实参A

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if(self.numberOfSectionsInTableViewHandle) return self.numberOfSectionsInTableViewHandle(tableView);
    return 0;
}

第四步:上一步执行了block后,就会回调到下面的block内

.zfc_numberOfSectionsInTableView(^NSInteger(UITableView *tableView){
          //第三步完了会回调到这里,此处返回结果
          return 3;
})

第五步:当第四步中的block回调完了,因为它是一个有返回值的block,所以它的返回值又会被numberOfSectionsInTableView方法接受,这样就返回了tableView有多少段

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
   //此处接受*numberOfSectionsInTableViewHandle*的返回结果
    if(self.numberOfSectionsInTableViewHandle) return self.numberOfSectionsInTableViewHandle(tableView);
    return 0;
}

以上就是zfc_numberOfSectionsInTableView的主要实现过程

3. collectionView的链式调用

collectionView的链式调用思想和上面的tableView的思想一样,而且调用方式也差不多,核心代码如下

    __weak typeof(self)weakSelf = self;
    [self.collectionView configure:^(ZFC_CollectionViewChainnedInvokeCreater *creater) {
        creater.zfc_collectionViewConfigure(collectionViewConfig)
        .zfc_numberOfSectionsInCollectionView(^NSInteger(UICollectionView *collectionView){
            return 3;
        })
        .zfc_numberOfItemsInSection(^NSInteger(UICollectionView *collectionView,NSInteger section) {
            return weakSelf.dataSource.count;
        })
        .zfc_sizeForItemAtIndexPath(^CGSize(UICollectionView *collectionView,NSIndexPath *indexPath) {
            return CGSizeMake(115 , 100);
        })
        .zfc_cellForItemAtIndexPath(^(UICollectionView *collectionView,__kindof ZFC_CollectionViewCell *cell, NSIndexPath *indexPath) {
            cell.myLabel.text = [NSString stringWithFormat:@"%@%@",weakSelf.dataSource[indexPath.row],isXIB?@"->XIB":@""];
            cell.contentView.backgroundColor = [UIColor redColor];
        })
        .zfc_referenceSizeForHeaderInSection(^CGSize(UICollectionView *collectionView, NSInteger section) {
            return CGSizeMake(200, 40);
        })
        .zfc_collectionElementKindSectionHeader(^(UICollectionView *collectionView, __kindof ZFC_CollectionHeaderFooterView *sectionHeaderView, NSInteger section) {
            sectionHeaderView.myLabel.text = [NSString stringWithFormat:@"我是第-- %ld --段头%@",section,isXIB?@"->XIB":@""];
            sectionHeaderView.myView.backgroundColor = [UIColor greenColor];
        })
        .zfc_referenceSizeForFooterInSection(^CGSize(UICollectionView *collectionView, NSInteger section) {
            return CGSizeMake(200, 40);
        })
        .zfc_collectionElementKindSectionFooter(^(UICollectionView *collectionView, __kindof ZFC_CollectionHeaderFooterView *sectionFooterView, NSInteger section) {
            sectionFooterView.myLabel.text = [NSString stringWithFormat:@"我是第-- %ld --段尾%@",section,isXIB?@"->XIB":@""];
            sectionFooterView.myView.backgroundColor = [UIColor darkGrayColor];
        })
        .zfc_didSelectItemAtIndexPath(^(UICollectionView *collectionView, NSIndexPath *indexPath) {
             NSLog(@"我点击了%@",weakSelf.dataSource[indexPath.row]);
        });
    }];

4. 几个注意的地方

(1)在调用前,需要配置tableView和collectionView,在这个配置类,针对cell、sentionHeaderView、sectionFooterView的创建是支持xib创建的,但是如果是xib创建需要将对应的变量isCellXib、isSectionHeaderXib、isSectionFooterXib设置为YES
(2)在config里面还需要传入cellClass、sectionHeaderClass、sectionFooterClass用于内部注册使用
(3)tableView的配置示例:

    __block BOOL isXIB = YES;
    ZFC_TableViewConfig *tableViewConfig = [ZFC_TableViewConfig new];
    tableViewConfig.tableView = self.tableView;
    tableViewConfig.isCellXib = isXIB;
    tableViewConfig.cellClass = [getClassFromClassString(@"ZFC_TableViewCell", isXIB) class];
    tableViewConfig.isSectionHeaderXib = isXIB;
    tableViewConfig.sectionHeaderClass = [getClassFromClassString(@"ZFC_TableViewHeaderFooterView", isXIB) class];
    tableViewConfig.isSectionFooterXib = isXIB;
    tableViewConfig.sectionFooterClass = [getClassFromClassString(@"ZFC_TableViewHeaderFooterView", isXIB) class];
    tableViewConfig.canDelete = YES;

(4)collectionView的配置示例:

    __block BOOL isXIB = YES;
    ZFC_CollectionConfig *collectionViewConfig = [ZFC_CollectionConfig new];
    collectionViewConfig.collectionView = self.collectionView;
    collectionViewConfig.isCellXib = isXIB;
    collectionViewConfig.cellClass = [getClassFromClassString(@"ZFC_CollectionViewCell", isXIB) class];
    collectionViewConfig.isSectionHeaderXib = isXIB;
    collectionViewConfig.sectionHeaderClass = [getClassFromClassString(@"ZFC_CollectionHeaderFooterView", isXIB) class];
    collectionViewConfig.isSectionFooterXib = isXIB;
    collectionViewConfig.sectionFooterClass = [getClassFromClassString(@"ZFC_CollectionHeaderFooterView", isXIB) class];

5. 总结

以上就是tableView和collectionView的链式调用部分。最后,我再提一下链式创建UI和使用的小工具库ZFCChainedCreater,支持pod导入pod 'ZFCChainedCreater', '~> 1.0.2',github地址:https://github.com/zfc769956454/ZFCChainedCreater

你可能感兴趣的:(OC 链式编程第二部分 - 调用篇)