含有 tableView 的 ViewController 的瘦身方法

前言

最近在開發(fā) iOS 時,發(fā)現(xiàn)有很多的業(yè)務(wù)展示界面都是使用了 tableView,而且大部分展示的界面都是沒有很復(fù)雜的業(yè)務(wù)交互和界面結(jié)構(gòu)。例如下面的2個界面


列表一
列表二

一般來說,正常的開發(fā)這上面的2個界面,會寫出一下的代碼

@interface ViewController1: UIViewController <UITableViewDataSource, UITableViewDelegate>
/* 省略內(nèi)容*/
@end 

@implementation ViewController1

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.manager getDataSourceCount];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     ViewController1CellConfig  *config = [self.manager configInfoFromIndexPath: indexPath];
      ViewController1Cell * cell = [tableView dequeueReusableCellWithIdentifier:@"ViewController1Cell" forIndexPath:indexPath ];
     [cell configCell: ViewController1CellConfig];
     return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return ViewControllerCellHeight;
}
@end
@interface ViewController2: UIViewController <UITableViewDataSource, UITableViewDelegate>
/* 省略內(nèi)容*/
@end 

@implementation ViewController2

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.manager getDataSourceCount];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     ViewController2CellConfig  *config = [self.manager configInfoFromIndexPath: indexPath];
      ViewController2Cell * cell = [tableView dequeueReusableCellWithIdentifier:@"ViewController2Cell" forIndexPath:indexPath ];
     [cell configCell: ViewController2CellConfig];
     return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return ViewControllerCellHeight;
}
@end

一對比,會發(fā)現(xiàn)這2個 ViewController 中的代碼非常類似,而在我們的業(yè)務(wù)項目中,遠遠不止2個類似的代碼。既然代碼都是如此的類似,那么,我們是否可以將這部分代碼抽離出來,抽象出一個公共的,復(fù)用的類呢。答案是肯定的。

觀察上面代碼可以發(fā)現(xiàn), 上述代碼,其實都是在重復(fù)一個流程, ViewController 從 manager 中獲取到數(shù)據(jù), 然后在將數(shù)據(jù)傳遞到 tableView 和 tableViewCell。 因此,只要我們確定了數(shù)據(jù)傳輸?shù)慕涌?,就可以將?shù)據(jù)傳輸這部分代碼抽象出來。

定義 Manager 到 ViewController 的接口

從上面代碼可知, 從 manager 中獲取數(shù)據(jù)的接口有 getDataSourceCountconfigInfoFromIndexPath 所以,我們可以使用 Protocol 的特性, 定義一個接口文件EPCommonManagerProviderDelegagte,如下:


@protocol EPCommonManagerProviderDelegagte <NSObject>

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

- (NSUInteger)numberOfRowsInSection:(NSInteger)section;

@end

這個協(xié)議一共定義了2個內(nèi)容,負責(zé)提供 tableView 行數(shù)的 numberOfRowsInSection 和 負責(zé)提供 tableViewCell 配置數(shù)據(jù)的 cellConfigurationWithIndexPath

定義 ViewController 到 tableView 和 Cell 的接口

由于 ViewController 到 tableView 的接口就是 dataSource 的協(xié)議內(nèi)容,這里不多討論。 下面主要定義了 ViewController 到 Cell 的接口EPCommonCellConfigDelegate

@protocol EPCommonCellConfigDelegate <NSObject>
- (void)cellConfig:(id)cellConfiguration;
@end

抽離出 ViewController 中 tableView 的 dataSource

@interface EPCommonTableViewProvider : NSObject <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) id<EPCommonCellManagerProviderDelegagte> manager;

@property (nonatomic, strong) NSString *cellIdentifier;

@property (nonatomic, assign) CGFloat cellHeight;

@end


@implementation EPCommonTableViewProvider


- (instancetype)init {
    if (self = [super init]) {
        _cellHeight = 44;
    }
    return self;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (self.manager && [self.manager respondsToSelector:@selector(numberOfRowsInSection:)]) {
        return [self.manager numberOfRowsInSection:section];
    }
    return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (self.cellIdentifier.length == 0) {
        return [[UITableViewCell alloc] init];
    }
    id<EPCommonCellConfigDelegate> cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier forIndexPath:indexPath];
    
    if (self.manager && [self.manager respondsToSelector:@selector(cellConfigurationWithIndexPath:)]) {
        id cellConfiguration = [self.manager cellConfigurationWithIndexPath:indexPath];
        if (cell && [cell respondsToSelector:@selector(cellConfig:)]) {
            [cell cellConfig:cellConfiguration];
        }
    }
    return (UITableViewCell *)cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return self.cellHeight;
}
@end

實際使用

  1. manager 實現(xiàn) EPCommonManagerProviderDelegagte協(xié)議
@interface ViewController1Manager : NSObject <EPCommonManagerProviderDelegagte>
@end
@implementation ViewController1Manager


- ( *)cellConfigurationWithIndexPath:(NSIndexPath *)indexPath {
    return [[ViewControllerCell1Config alloc] initWithModel:self.dataSource[indexPath.row] sortType:self.sortType];
}

- (NSUInteger)numberOfRowsInSection:(NSInteger)section {
    return self.dataSource.count;
}

@end

  1. cell 實現(xiàn) EPCommonCellConfigDelegate 協(xié)議
@interface ViewController1Cell : UITableViewCell <EPCommonCellConfigDelegate>
@end
@implementation ViewController1Cell
- (void)cellConfig:(ViewControllerCell1Config *)config {
  /* 配置 cell */
}
@end
  1. 將 EPCommonTableViewProvider 配置 給 tableView 的 dataSource
@interface ViewController1: UIViewController 
/* 省略內(nèi)容*/
@property (nonatomic, strong) EPCommonTableViewProvider *provider;
@property (nonatomic, strong) ViewController1Manager *manager;
@property (nonatomic, strong) UITableView *tableView;
@end 

@implementation ViewController1

- (EPCommonTableViewProvider *)provider {
    if (_provider == nil) {
        _provider = [[EPCommonTableViewProvider alloc] init];
        _provider.manager = self.manager;
        _provider.cellHeight = 50;
        _provider.cellIdentifier = @"ViewController1Cell";
    }
    return _provider;
}

- (UITableView *)tableView {
    if (_tableView == nil) {
        _tableView = [[UITableView alloc] init];
        _tableView.dataSource = self.provider;
        [_tableView registerNib:[UINib nibWithNibName:@"ViewController1Cell" bundle:nil] forCellReuseIdentifier:@"ViewController1Cell"];
    }
    return _tableView;
}
@end

對于簡單的展示頁面,manager 和 cell 的代碼幾乎沒有變化,但是抽離出一個 EPCommonTableViewProvider 可以有效的減少 ViewController 中代碼行數(shù),并且也可以減少重復(fù)代碼的數(shù)量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容