2014-09-11 60 views
0

我在网上找到了一个例子,说明如何分离UITableview的数据源以使代码更加可重用。但是,在这段代码中,它使用一个块代替委托来更新单元。到目前为止,在我的项目中,我一直在使用代表以保持一致性,所以我希望它保持这种方式,所以如果有人能够解释更好的块并帮助我重构下面的示例代码以包含delegates而不是该块,我很乐意。我使用的示例来自http://www.objc.io/issue-1/lighter-view-controllers.html;了解委托与区块。 (重构代码使用代表团而不是块)

// 
// ArrayDataSource.h 
// objc.io example project (issue #1) 
// 

#import <Foundation/Foundation.h> 


typedef void (^TableViewCellConfigureBlock)(id cell, id item); 


@interface ArrayDataSource : NSObject <UITableViewDataSource> 

- (id)initWithItems:(NSArray *)anItems 
cellIdentifier:(NSString *)aCellIdentifier 
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock; 

- (id)itemAtIndexPath:(NSIndexPath *)indexPath; 

@end 

.M

// 
// ArrayDataSource.h 
// objc.io example project (issue #1) 
// 

#import "ArrayDataSource.h" 


@interface ArrayDataSource() 

@property (nonatomic, strong) NSArray *items; 
@property (nonatomic, copy) NSString *cellIdentifier; 
@property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock; 

@end 


@implementation ArrayDataSource 

- (id)init 
{ 
    return nil; 
} 

- (id)initWithItems:(NSArray *)anItems 
cellIdentifier:(NSString *)aCellIdentifier 
configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock 
{ 
    self = [super init]; 
    if (self) { 
     self.items = anItems; 
     self.cellIdentifier = aCellIdentifier; 
     self.configureCellBlock = [aConfigureCellBlock copy]; 
    } 
    return self; 
} 

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


#pragma mark UITableViewDataSource 

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

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

@end 

并对其在UIViewController用法是;

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; 

我尝试每天学习新的东西,如果有人能够帮助,这将是伟大的。有一天,我希望作为一个开发人员改进:)

我明白数据源的分离,但使用块而不是委托对我来说是新的(怪异的)。

回答

2

事实上,在你的例子中,ArrayDataSource类是一个“泛型”类,用于你的所有UITableView的数据源。

如果仔细观察ArrayDataSource(ArrayDataSource.m)的实现,您会看到它调用UITableViewDatasource的经典方法(numberOfRowsInSection:cellForRowAtIndexPath: ...)。但是,当泛型类必须为特定索引路径配置单元格的内容时,它不知道如何处理id item,因此它会调用特定块(使用self.configureCellBlock(cell, item);)将该行为从泛型类中外化。

块的想法就像函数指针,你只是告诉泛型ArrayDatasource类,当它必须配置线self.configureCellBlock(cell, item);上的一个单元格的内容时调用什么函数。在你的情况下,单元格将显示照片的名称(cell.label.text = photo.name;)。

因此,在这种情况下,你还在使用一个UITableView的数据源概念ArrayDatasource类,你可以把你所有的需求为默认UITableViewDatasourceArrayDataSource.m(如实施heightForRowAtIndexPath:等等...) ,以防止所有tableView的数据源的复制粘贴(如果您的应用程序有很多UITableView)。 这里的块的目的不是要取代数据源的概念,而是更方便地告诉一个通用类该怎么做...

我希望我很清楚,但解释这些概念并不总是很容易! :)

+0

非常感谢这是非常有帮助的。 :) – DevC 2014-09-11 12:36:20