如何通过代理方法的使用来简化控制器的代码量

129 阅读1分钟
  • #import "PhotosViewController.h"
static NSString * const PhotoCellIdentifier = @"PhotoCell";

@interface PhotosViewController () <UITableViewDataSource, UITableViewDelegate>

// 引入外部数据源 , 代理方法那些冗余代码都统一放到外部文件中:
@property (nonatomic, strong) ArrayDataSource *photosArrayDataSource;

@end

@implementation PhotosViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.title = @"Photos";
    // 布局表视图:
    [self setupTableView];
}

/// 布局表视图:
- (void)setupTableView {
    // 通过回调方法拿到每一行的那个cell和对应的数据模型:
    // 其实block就是一种在Objective-C语言中 => "函数是第一公民" 的体现:
    // 把函数赋值给一个变量configureCell , configureCell带着这个函数到处走...
    TableViewCellConfigureBlock configureCell = ^(PhotoCell *cell, Photo *photo) {
        [cell configureForPhoto:photo];
    };
    NSArray *photos = [AppDelegate sharedDelegate].store.sortedPhotos;
    self.photosArrayDataSource = [[ArrayDataSource alloc] initWithItems:photos cellIdentifier:PhotoCellIdentifier configureCellBlock:configureCell];
    // tableView绑定数据源:
    self.tableView.dataSource = self.photosArrayDataSource;
    // tableView绑定视图源:
    [self.tableView registerNib:[PhotoCell nib] forCellReuseIdentifier:PhotoCellIdentifier];
}

#pragma mark - <UITableViewDelegate>
/// 点击跳转下一页:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:NSStringFromClass([PhotoViewController class]) bundle:nil];
    photoViewController.photo = [self.photosArrayDataSource itemAtIndexPath:indexPath];
    [self.navigationController pushViewController:photoViewController animated:YES];
}

@end
  • ArrayDataSource.h
/// 回调方法
/// @param cell cell
/// @param item 数据模型
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

  • ArrayDataSource.m
#import "ArrayDataSource.h"

@interface ArrayDataSource ()

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

@end


@implementation ArrayDataSource

// 不允许使用init初始化方法:
- (id)init {
    return nil;
}


/// 初始化方法
/// @param anItems 数据源数组
/// @param aCellIdentifier 复用标识符
/// @param aConfigureCellBlock 回调方法
- (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;
}


/// 返回该indexPath下的那个数据模型
/// @param indexPath indexPath位置
- (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];
    // 把那一位置下的cell和数据模型都传递出去:
    self.configureCellBlock(cell, item);
    
    return cell;
}

@end