iOS-将UITableViewDataSource协议和其他协议分离开

原文链接:http://www.objc.io/issue-1/lighter-view-controllers.html 本文并未全部翻译,只是摘录翻译自己觉得有意思的部分。


在iOS项目中,控制器经常是最大的文件, 并且它们中经常有不必要包含的代码。在大多数情况下,控制器是所有代码中复用性最差的。让我们来看一些能让你的控制器瘦身,让代码更具有复用性,让代码放在更合适的地方的技术。


#1将UITableViewDataSource协议和其他协议分离开


在为你的控制器瘦身的技术中,最强力的之一是将你代码中的UITableViewDataSource部分移到属于他自己的类中。 如果你多做几次这样的操作,你就会开始察觉这种模式并能写出具有复用性的代码。


举个例吧,在我们的示例程序中,有一个PhotosViewController类并具有如下方法

# pragma mark Pragma 

- (Photo*)photoAtIndexPath:(NSIndexPath*)indexPath {
    return photos[(NSUInteger)indexPath.row];
}

- (NSInteger)tableView:(UITableView*)tableView 
 numberOfRowsInSection:(NSInteger)section {
    return photos.count;
}

- (UITableViewCell*)tableView:(UITableView*)tableView 
        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    PhotoCell* cell = [tableView dequeueReusableCellWithIdentifier:PhotoCellIdentifier 
                                                      forIndexPath:indexPath];
    Photo* photo = [self photoAtIndexPath:indexPath];
    cell.label.text = photo.name;
    return cell;
}

这段代码中的一大部分要与数组打交道,只有一小部分是专属于这个控制器所管理的photo对象们的。所以让我们尝试将关于数组的代码转移到属于它们自己的类中。我们使用一个block去设置cell,你也可以使用代理,一切都取决于你的需求和口味。


@implementation ArrayDataSource

- (id)itemAtIndexPath:(NSIndexPath*)indexPath {
    return items[(NSUInteger)indexPath.row];
}

- (NSInteger)tableView:(UITableView*)tableView 
 numberOfRowsInSection:(NSInteger)section {
    return items.count;
}

- (UITableViewCell*)tableView:(UITableView*)tableView 
        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    id cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier
                                              forIndexPath:indexPath];
    id item = [self itemAtIndexPath:indexPath];
    configureCellBlock(cell,item);
    return cell;
}

@end


在这个DataSource中实现的三个方法,可以从你的控制器中移除了,然后,你可以为这个类创建一个实例,并将其设置为你的table view的datasourse。


void (^configureCell)(PhotoCell*, Photo*) = ^(PhotoCell* cell, Photo* photo) {
   cell.label.text = photo.name;
};
photosArrayDataSource = [[ArrayDataSource alloc] initWithItems:photos
                                                cellIdentifier:PhotoCellIdentifier
                                            configureCellBlock:configureCell];
self.tableView.dataSource = photosArrayDataSource;


现在你不用再担心怎么去将ndexPath映射到数组中的某个位置了,每次你想在一个tableview上显示一个数组,你都可以复用这段代码。你更可以实现更丰富的接口,并将它们用于你所有的tableview上。


美妙的事是我们可以单独测试DataSource,并永远不需要重写这些可复用的代码。同样的概念也适用于除数组外的其他情况。


此外,这种方法也适用于其他的协议。一个明显的候选就是UICollectionViewDataSource。这种方式会给你极大的可变性,比如,在开发中,你想将一个TableView换成CollectionView,你不需要改变ViewController中的任何代码。你甚至可以使你的datasource同时支持tableview和collectionview。


这篇文章的这部分是我觉得最有趣的部分,在以前的开发中从未想过将Datasource部分独立开来,相信读了这段你也已经体会到了将DataSource单独分离出来的好处,代码复用性提高,代码耦合性降低,是非常实用的技巧。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值