我在网上找到了一个示例,说明如何分离 UITableview 的数据源以提高代码的可重用性。但是,在此代码中,它使用 block 而不是委托(delegate)来更新单元格。到目前为止,在我的项目中,我一直在使用委托(delegate),为了保持一致性,我希望它保持这种方式,所以我希望有人能解释更好的 block 并帮助我重构下面的示例代码以包含 delegates
的 block 。我使用的示例来自 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;
我每天都尝试学习新东西,如果有人能提供帮助,那就太好了。作为一名开发人员,我希望一天一天地进步 :)
我理解数据源的分离,但使用 block 而不是委托(delegate)对我来说是新的(奇怪的)。
最佳答案
事实上,在您的示例中,ArrayDataSource 类是用于所有 UITableView 数据源的“通用”类。
如果您仔细查看 ArrayDataSource (ArrayDataSource.m) 的实现,您会发现它调用了 UITableViewDatasource 的经典方法(numberOfRowsInSection:
, cellForRowAtIndexPath:
...)。但是当泛型类必须为特定的indexPath配置单元格的内容时,它不知道如何处理id item
,所以它调用特定的 block (用self .configureCellBlock(cell, item);
) 从通用类中外部化此行为。
block 的概念就像函数指针,你只是告诉通用 ArrayDatasource 类,当它必须在行 self.configureCellBlock(cell, item) 上配置单元格的内容时调用什么函数;
。在您的例子中,单元格将显示照片的名称 (cell.label.text = photo.name;
)。
因此,在这种情况下,您仍然在 ArrayDatasource
类中使用 UITableView 的数据源概念,并且您可以将默认 UITableViewDatasource
的所有需求放在ArrayDataSource.m
(比如实现 heightForRowAtIndexPath:
等等...),以防止对所有 tableView 的数据源进行复制粘贴(如果您的应用程序具有许多 UITableView
)。
这里的 block 的目的不是要取代数据源概念,而是更方便的方式来告诉泛型类要做什么...
我希望我很清楚,但解释这些概念并不总是那么容易! :)
关于ios - 了解委托(delegate)与 block 。 (重构代码以使用委托(delegate)而不是 block ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25783071/