ios - 了解委托(delegate)与 block 。 (重构代码以使用委托(delegate)而不是 block )

标签 ios objective-c uitableview delegates objective-c-blocks

我在网上找到了一个示例,说明如何分离 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/

相关文章:

导航栏上方的 iOS 空白空间?

ios - 如何使用一个 var 或 let 从一个 View Controller 到另一个 View Controller

iphone - 如何将整数值添加到 NSMutableArray?

ios - 在 IOS 中存储聊天消息和对话的最佳方式是什么

ios - 从 firebase 下载的图像无法正确缩放,并且直到在表格 View 单元格上滚动后才显示

iPhone UITableView 与 UISearchBar 和刷新部分索引

ios - 点击特定标记如何获取标题名称

ios - 将存档上传到 App Store 时出错 : The bundle is invalid

iphone - 在 UITextView 中成功滑动?

ios - 将表中的特定行从 void 更改为空