iOS - UITableview代理方法與Viewcontroller分離


在objcio.cn中有一篇文章更輕量的 View Controllers.其中有一小節(jié),是說(shuō)把UITableview的datasource和delegate分離出Viewcontroller的。我也試著實(shí)現(xiàn)了一下,隨便把思路總結(jié)下~

DEMO


建議先下載demo,再結(jié)合下面的分析,會(huì)好理解點(diǎn)。地址https://github.com/Resory/RYDatasource

邏輯


  • 既然我們要把UITableview的協(xié)議方法分離出來(lái),就得有一個(gè)人去接,在這里我們把這個(gè)人叫Datasource??梢岳斫馑鼮?code>中間人。這個(gè)中間人就是以后實(shí)現(xiàn)UITableview協(xié)議方法的地方。

  • 中間人實(shí)現(xiàn)UITableview協(xié)議方法,就得知道UITableview的數(shù)據(jù),復(fù)用事件等要素。這些數(shù)據(jù)由Viewcontroller來(lái)傳。這三個(gè)要素分別定義為serverData,cellIdentifiers,configSelectedBlock

  • 自此我們可以知道,只要Viewcontroller傳了serverData,cellIdentifiers,configSelectedBlock這三個(gè)基本參數(shù),中間人就可以實(shí)現(xiàn)UITableview協(xié)議方法了。

實(shí)現(xiàn)


  • 在Viewcontroller.m中。我們命名了三個(gè)全局變量,如下代碼
    configSelectedBlock不需要設(shè)置全局,到時(shí)候在函數(shù)中直接生成即可)
// Viewcontroller.m
@property (nonatomic, strong) NSMutableArray *serverData;       // 服務(wù)器返回的數(shù)據(jù)
@property (nonatomic, strong) NSMutableArray *cellIdentifiers;  // cell樣式標(biāo)示
@property (nonatomic, strong) TDatasource *datasource;          // 中間人
  • 還是在Viewcontroller.m中.我們把數(shù)據(jù),復(fù)用,事件設(shè)置好后,看看如何調(diào)用中間人。
數(shù)據(jù)
// Viewcontroller.m  
- (void)configData
{
    // 服務(wù)器返回的數(shù)據(jù)
    _serverData = [[NSMutableArray alloc] init];
    // 實(shí)體設(shè)置
    TModelOne *one = [[TModelOne alloc] init];
    TModelOne *two = [[TModelOne alloc] init];
    
    one.name = @"奇犽";
    one.imageName = @"001.jpg";
    
    two.name = @"拿尼加";
    two.imageName = @"002.jgp";
    
    [_serverData addObject:one];
    [_serverData addObject:two];
}
復(fù)用
// Viewcontroller.m  
- (void)configIdentifier
{
    // cell復(fù)用設(shè)置
    _cellIdentifiers = [[NSMutableArray alloc] init];
    [_cellIdentifiers addObject:NSStringFromClass([TCellOne class])];
    [_tableview registerNib:[TCellOne nib] forCellReuseIdentifier:_cellIdentifiers[0]];
}
初始化"中間人"
// Viewcontroller.m  
- (void)configDataSource
{
    // cell數(shù)據(jù)
    [self configData];
    
    // cell復(fù)用
    [self configIdentifier];
    
    // cell事件
    RYCellSelectedBlock cellSelectedBlock = ^(id obj){
        // cell點(diǎn)擊事件
        [self cellSelectedWithObj:obj];
    };
    
    // 初始化dataSource
    _datasource = [[TDatasource alloc] initWithServerData:_serverData
                                       andCellIdentifiers:_cellIdentifiers];
    _datasource.cellSelectedBlock = cellSelectedBlock;
}
  • 中間人設(shè)置為UITableview的協(xié)議方法執(zhí)行者
// Viewcontroller.m  
- (void)configTableView
{
    // 把_dataSource設(shè)置成_tableview的代理,以后所有代理方法都在_dataSource實(shí)現(xiàn)
    _tableview.delegate = _datasource;
    _tableview.dataSource = _datasource;
    _tableview.tableFooterView = [UIView new];
}
  • 我們進(jìn)去中間人看看它到底做了什么,下面的代碼可以清晰看到。中間人除了多了初始化方法來(lái)接受數(shù)據(jù)外,其他方法都是UITableview的協(xié)議方法

// TDatasource.m

- (id)initWithServerData:(NSArray *)serverData
      andCellIdentifiers:(NSArray *)identifiers
{
    self = [super init];
    if(self)
    {
        self.serverData = serverData;           // 數(shù)據(jù)
        self.cellIdentifiers = identifiers;     // 復(fù)用
    }
    
    return self;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifiers[0]
                                                            forIndexPath:indexPath];
    // cell的數(shù)據(jù)填充(cell的category方法)
    [cell configCellWithEntity:self.serverData[indexPath.row]];
    
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 80.0;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // cell點(diǎn)擊事件
    self.cellSelectedBlock(indexPath);
}

  • 最后我們來(lái)看下cell里面的方法,也是一眼能看懂的代碼··

#import "TCellOne.h"
#import "TModelOne.h"

@implementation TCellOne

- (void)awakeFromNib {
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (void)configCellWithEntity:(id)entity
{
    if(entity)
    {
        TModelOne *model = entity;
        self.name.text = model.name;
        self.avartar.image = [UIImage imageNamed:model.imageName];
    }
}
  • 挫就挫吧,總得來(lái)張圖。。
奇犽~.png

最后


  • UITableview協(xié)議方法分離出Viewcontroller后,Viewcontroller確實(shí)清爽了不少。但同時(shí)也帶了不便,比如說(shuō)又多了一個(gè)文件,又比如說(shuō)cell的點(diǎn)擊事件就得用一個(gè)block來(lái)回調(diào),如果是cell里面的子view的點(diǎn)擊事件就更不利索了。所以有利就有弊吧。還是得結(jié)合實(shí)際選擇最適合自己的開(kāi)發(fā)方式~

  • 如果你有疑問(wèn)或者發(fā)現(xiàn)錯(cuò)誤請(qǐng)留言給我

  • 喜歡就點(diǎn)個(gè)贊,點(diǎn)個(gè)星什么的。3Q~~

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

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

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