iOS - UITableview代理方法與Viewcontroller分離


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

DEMO


建議先下載demo,再結合下面的分析,會好理解點。地址https://github.com/Resory/RYDatasource

邏輯


  • 既然我們要把UITableview的協議方法分離出來,就得有一個人去接,在這里我們把這個人叫Datasource。可以理解它為中間人。這個中間人就是以后實現UITableview協議方法的地方。

  • 中間人實現UITableview協議方法,就得知道UITableview的數據復用事件等要素。這些數據由Viewcontroller來傳。這三個要素分別定義為serverDatacellIdentifiersconfigSelectedBlock

  • 自此我們可以知道,只要Viewcontroller傳了serverDatacellIdentifiersconfigSelectedBlock這三個基本參數,中間人就可以實現UITableview協議方法了。

實現


  • 在Viewcontroller.m中。我們命名了三個全局變量,如下代碼
    configSelectedBlock不需要設置全局,到時候在函數中直接生成即可)
// Viewcontroller.m
@property (nonatomic, strong) NSMutableArray *serverData;       // 服務器返回的數據
@property (nonatomic, strong) NSMutableArray *cellIdentifiers;  // cell樣式標示
@property (nonatomic, strong) TDatasource *datasource;          // 中間人
  • 還是在Viewcontroller.m中.我們把數據,復用,事件設置好后,看看如何調用中間人
數據
// Viewcontroller.m  
- (void)configData
{
    // 服務器返回的數據
    _serverData = [[NSMutableArray alloc] init];
    // 實體設置
    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];
}
復用
// Viewcontroller.m  
- (void)configIdentifier
{
    // cell復用設置
    _cellIdentifiers = [[NSMutableArray alloc] init];
    [_cellIdentifiers addObject:NSStringFromClass([TCellOne class])];
    [_tableview registerNib:[TCellOne nib] forCellReuseIdentifier:_cellIdentifiers[0]];
}
初始化"中間人"
// Viewcontroller.m  
- (void)configDataSource
{
    // cell數據
    [self configData];
    
    // cell復用
    [self configIdentifier];
    
    // cell事件
    RYCellSelectedBlock cellSelectedBlock = ^(id obj){
        // cell點擊事件
        [self cellSelectedWithObj:obj];
    };
    
    // 初始化dataSource
    _datasource = [[TDatasource alloc] initWithServerData:_serverData
                                       andCellIdentifiers:_cellIdentifiers];
    _datasource.cellSelectedBlock = cellSelectedBlock;
}
  • 中間人設置為UITableview的協議方法執行者
// Viewcontroller.m  
- (void)configTableView
{
    // 把_dataSource設置成_tableview的代理,以后所有代理方法都在_dataSource實現
    _tableview.delegate = _datasource;
    _tableview.dataSource = _datasource;
    _tableview.tableFooterView = [UIView new];
}
  • 我們進去中間人看看它到底做了什么,下面的代碼可以清晰看到。中間人除了多了初始化方法來接受數據外,其他方法都是UITableview的協議方法

// TDatasource.m

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifiers[0]
                                                            forIndexPath:indexPath];
    // cell的數據填充(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點擊事件
    self.cellSelectedBlock(indexPath);
}

  • 最后我們來看下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];
    }
}
  • 挫就挫吧,總得來張圖。。
奇犽~.png

最后


  • UITableview協議方法分離出Viewcontroller后,Viewcontroller確實清爽了不少。但同時也帶了不便,比如說又多了一個文件,又比如說cell的點擊事件就得用一個block來回調,如果是cell里面的子view的點擊事件就更不利索了。所以有利就有弊吧。還是得結合實際選擇最適合自己的開發方式~

  • 如果你有疑問或者發現錯誤請留言給我

  • 喜歡就點個贊,點個星什么的。3Q~~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容