美文网首页
OC 链式编程第二部分 - 调用篇

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

作者: 风云雪獒 | 来源:发表于2018-11-12 18:05 被阅读0次

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

相关文章

  • 像swift一样书写OC代码OC链式编程实践

    链式编程特点 链式编程 = 点语法 事物 串联 同样的hello word代码 OC和swift调用函数时候最大的...

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

    1. UITableView的常规调用 上面就是我们常规使用tableView的代码。在每次使用tableView...

  • OC链式编程的一个实践

    所谓链式编程,基本都是调用一个方法的时候返回对象本身,然后可以继续调用方法。以OC为例: 不过OC使用中括号调用方...

  • 链式文件生成器原理分析(一)

    在OC里面实现链式编程,可以使用返回调用者自身来实现。但是类有很多,每个类也有很多方法,假如要实现链式编程,则需要...

  • iOS-链式编程

    函数式编程------->链式编程 函数式编程: 调用方式 我们最终目的是将函数式编程转换为链式编程:首先将调用方...

  • (转载)链式文件生成器原理分析(一)

    此文章由热心网友 ccSundayChina授权转载 在OC里面实现链式编程,可以使用返回调用者自身来实现。但是类...

  • 编程思想-链式编程

    编程思想-链式编程 链式编程(链式调用)的主要表现是支持点语法结构的代码,代表库可以参照 Masonry 或 Sn...

  • iOS 链式编程

    链式编程是OC中一种很好的设计模式。框架中使用链式编程,会让框架使用者感觉写的代码更加美观简洁。 链式编程的效果 ...

  • OC 链式编程

    _ config.h _ View Example 既然已经决定,就勇敢的去吧。 决定吧

  • OC:链式编程

    概念: 链式编程:将多个业务逻辑(方法)通过“.”(点号)串联起来的一种代码风格,形似链条,故称链式编程。核心思想...

网友评论

      本文标题:OC 链式编程第二部分 - 调用篇

      本文链接:https://www.haomeiwen.com/subject/nwucfqtx.html