iOS控制器瘦身芥备,封裝TableViewDataSource和TableViewDelegate

最近有些變懶了, 學習的步伐放慢了很多, 估計玩懶了身子, 連博客都少寫了咯.

之前有個老鐵問我, 怎么去封裝一個低耦合可服用的TableViewController, 那時候沒多說啥, 直接把我封裝的框架丟給他了, 但他還是有很多亂七八糟的問題問我, 干脆直接寫一篇博文當成教程好了.

一、MVVM模式
由于這里我是用MVVM模式來封裝的, 這里我就簡單點, 通俗點, 易懂點的說說MVVM吧.

很多老鐵都習慣于用MVC, 雖然有聽過MVVM, 但也沒去咋了解, 其實MVVM沒有那么復雜, 傳統(tǒng)的MVC是有Model, Views, Controller, 而MVVM只是在這個得基礎上加了一個ViewModel, 并且弱化了Controller的職能.

MVC: Model, Views, Controller MVVM: Model, Views, ViewModel

那么弱化了的Controller就負責作為一個粘合劑, 像樂高積木一樣, 把Model, Views, ViewModel組裝在一起, 成為一個模塊, 而Model, Views, ViewModel分別又是獨立的個體, 誰都不會離不開誰.

大概就醬紫吧, 如果有更好的說法, 歡迎各位老鐵補充補充哈~~

動工前的思考
這里說一下, CLTableViewController是我自己封裝的TableViewController, 由于我比較懶, 所以里面直接集成了MJRefresh, 各位老鐵隨意噴哈.

這里說一下思路, 由于TableView還有TableViewDataSource, TableViewDelegate, 所以這里我們需要把兩個模塊分開, 這樣子就不會造成代碼臃腫的情況啦.

注意: 這里不包括各位的業(yè)務邏輯哈

二坟岔、封裝TableViewDataSource
剛剛其實還說漏了一個, 除去TableViewDataSource, TableViewDelegate, 期是還有一個ViewModel層, 這個是用來請求數(shù)據(jù)的.

現(xiàn)在我們先來看TableViewDataSource:

#import <Foundation/Foundation.h>
#import "CLTableViewBaseModel.h"
 
@interface CLTableViewDataSource : NSObject <UITableViewDataSource>
 
@property (nonatomic, strong, readonly) CLTableViewBaseModel *cl_viewModel;
 
- (instancetype)initTableViewDataSourceWithViewModel:(CLTableViewBaseModel *)viewModel;
 
@end
#import "CLTableViewDataSource.h"
 
@interface CLTableViewDataSource ()
 
@property (nonatomic, strong, readwrite) CLTableViewBaseModel *cl_viewModel;
 
@end
 
@implementation CLTableViewDataSource
 
- (instancetype)initTableViewDataSourceWithViewModel:(CLTableViewBaseModel *)viewModel {
    
    self = [super init];
    
    if (self) {
        
        self.cl_viewModel = viewModel;
    }
    
    return self;
}
 
- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section {
    
    return self.cl_viewModel.cl_dataSource.count;
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    
    if (!cell) {
        
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"UITableViewCell"];
    }
    
    return cell;
}
 
@end

在.h文件里, 只提供了一個供給指定ViewModel的初始化方法, 內(nèi)部的實現(xiàn), 所返回的數(shù)據(jù)源數(shù)量也是指定ViewModel的數(shù)組個數(shù), 默認返回一個系統(tǒng)的UITableViewCell, 這樣子就好了.

三拼苍、封裝TableViewDelegate
關于TableViewDelegate更多是采用系統(tǒng)的特性, 這里就沒寫什么內(nèi)部實現(xiàn)了:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "CLTableViewBaseModel.h"
 
@interface CLTableViewDelegate : NSObject <UITableViewDelegate>
 
@property (nonatomic, strong, readonly) CLTableViewBaseModel *cl_viewModel;
 
- (instancetype)initTableViewDelegateWithViewModel:(CLTableViewBaseModel *)viewModel;
 
@end
#import "CLTableViewDelegate.h"
 
@interface CLTableViewDelegate ()
 
@property (nonatomic, strong, readwrite) CLTableViewBaseModel *cl_viewModel;
 
@end
@implementation CLTableViewDelegate
 
- (instancetype)initTableViewDelegateWithViewModel:(CLTableViewBaseModel *)viewModel {
    
    self = [super init];
    
    if (self) {
        
        self.cl_viewModel = viewModel;
    }
    
    return self;
}
 
@end

只定義了一個指定ViewModel的初始化方法.

四徘郭、封裝CLTableViewBaseModel
關于ViewModel層, 這里我提供了三個方法, 兩個屬性:

#import <Foundation/Foundation.h>
#import "CLTableViewController.h"
 
@interface CLTableViewBaseModel : NSObject
 
@property (nonatomic, strong) NSMutableArray *cl_dataSource;
@property (nonatomic, weak, readonly) CLTableViewController *cl_tableViewController;
 
- (instancetype)initTableViewBaseModelWithController:(CLTableViewController *)viewController;
 
/**
 通過HTTP請求數(shù)據(jù)
 */
- (void)cl_tableViewHTTPRequest;
 
/**
 配置TableView每一條Cell所顯示的分割線
 */
- (void)cl_configTableViewWithDataSource;
 
@end
#import "CLTableViewBaseModel.h"
 
@interface CLTableViewBaseModel()
 
@property (nonatomic, weak, readwrite) CLTableViewController *cl_tableViewController;
 
@end
 
@implementation CLTableViewBaseModel
 
- (instancetype)initTableViewBaseModelWithController:(CLTableViewController *)viewController {
    
    self = [super init];
    
    if (self) {
        self.cl_tableViewController = viewController;
    }
    
    return self;
}
 
- (NSMutableArray *)cl_dataSource {
    
    if (!_cl_dataSource) {
        
        _cl_dataSource = [NSMutableArray array];
    }
    
    return _cl_dataSource;
}
 
- (void)cl_tableViewHTTPRequest {
    
}
 
- (void)cl_configTableViewWithDataSource {
    
    if (self.cl_dataSource.count > 0) {
        
        self.cl_tableViewController.cl_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    }
}
 
@end

這樣子就大功告成了, 接下來就是組裝起它們就可以了.

五来庭、組裝成CLTableViewController
剛剛我們已經(jīng)把三個模塊寫好了, 現(xiàn)在就開始組裝:

#import "CLViewController.h"
 
NS_ASSUME_NONNULL_BEGIN
@interface CLTableViewController : CLViewController
 
@property (nonatomic, strong, readonly) UITableView *cl_tableView;
 
/**
 初始化CLTableViewController
 @param style UITableViewStyle, 默認是UITableViewStylePlain
 @return CLTableViewController
 */
- (instancetype)initTableViewControllerWithStyle:(UITableViewStyle)style;
 
- (void)cl_removeRefresh;
- (void)cl_removeHeaderRefresh;
- (void)cl_removeFooterRefresh;
 
/**
 下拉刷新方法/上拉加載方法
 */
- (void)cl_dropDownRefresh;
- (void)cl_pullUpRefresh;
 
/**
 開始執(zhí)行下拉操作/結束下拉操作
 */
- (void)cl_dropDownBeginRefresh;
- (void)cl_dropDownEndRefresh;
 
/**
 開始執(zhí)行上拉操作/結束上拉操作
 */
- (void)cl_pullUpBeginRefresh;
- (void)cl_pullUpEndRefresh;
 
- (void)cl_setTableViewDelegate:(_Nullable id <UITableViewDelegate>)delegate
                     dataSource:(_Nullable id <UITableViewDataSource>)dataSource;
@end
NS_ASSUME_NONNULL_END
#import "CLTableViewController.h"
#import "MJRefresh.h"
#import "CLTableViewDelegate.h"
#import "CLTableViewBaseModel.h"
 
@interface CLTableViewController ()
 
@property (nonatomic, assign) UITableViewStyle tableViewStyle;
 
@property (nonatomic, strong, readwrite) UITableView *cl_tableView;
 
@property (nonatomic, strong) CLTableViewDelegate *cl_tableViewDelegate;
@property (nonatomic, strong) CLTableViewBaseModel *cl_ableViewBaseModel;
 
@end
 
@implementation CLTableViewController
 
- (instancetype)initTableViewControllerWithStyle:(UITableViewStyle)style {
    
    self = [super init];
    
    if (self) {
        
        [self setTableViewStyle:style];
    }
    
    return self;
}
 
#pragma mark - View Did Load
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.opaque = YES;
    self.automaticallyAdjustsScrollViewInsets = NO;
 
    self.view.backgroundColor = [UIColor whiteColor];
    
    [self cl_addRefresh];
}
 
- (UITableView *)cl_tableView {
    
    if (!_cl_tableView) {
        
        _cl_tableView = [[UITableView alloc] initWithFrame:self.view.frame
                                                     style:self.tableViewStyle];
        
        if (self.tableViewStyle == UITableViewStylePlain) {
            
            _cl_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        }
        
        _cl_tableView.opaque = YES;
    }
    
    return _cl_tableView;
}
 
- (void)cl_setTableViewDelegate:(id<UITableViewDelegate>)delegate
                     dataSource:(id<UITableViewDataSource>)dataSource {
    
    self.cl_tableView.delegate   = delegate;
    self.cl_tableView.dataSource = dataSource;
}
 
#pragma mark - Table View Delegate
- (CLTableViewDelegate *)cl_tableViewDelegate {
    
    if (!_cl_tableViewDelegate) {
        
        _cl_tableViewDelegate = [[CLTableViewDelegate alloc] initTableViewDelegateWithViewModel:self.cl_ableViewBaseModel];
    }
    
    return _cl_tableViewDelegate;
}
 
#pragma mark - Table View Base Model
- (CLTableViewBaseModel *)cl_ableViewBaseModel {
    
    if (!_cl_ableViewBaseModel) {
        _cl_ableViewBaseModel = [[CLTableViewBaseModel alloc] initTableViewBaseModelWithController:self];
    }
    
    return _cl_ableViewBaseModel;
}
 
#pragma mark - Refresh
- (void)cl_addRefresh {
    
    MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
        [self cl_dropDownRefresh];
    }];
    
    self.cl_tableView.mj_header = header;
    
    MJRefreshBackNormalFooter *refreshFooter = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
        [self cl_pullUpEndRefresh];
    }];
    
    self.cl_tableView.mj_footer = refreshFooter;
    
    [self.view addSubview:self.cl_tableView];
}
 
- (void)cl_dropDownRefresh {}
 
- (void)cl_pullUpRefresh {}
 
- (void)cl_dropDownBeginRefresh {
    [self.cl_tableView.mj_header beginRefreshing];
}
 
- (void)cl_dropDownEndRefresh {
    [self.cl_tableView.mj_header endRefreshing];
}
 
- (void)cl_pullUpBeginRefresh {
    [self.cl_tableView.mj_footer beginRefreshing];
}
 
- (void)cl_pullUpEndRefresh {
    [self.cl_tableView.mj_footer endRefreshing];
}
 
- (void)cl_removeRefresh {
    
    self.cl_tableView.mj_header = nil;
    self.cl_tableView.mj_footer = nil;
}
 
- (void)cl_removeHeaderRefresh {
    self.cl_tableView.mj_header = nil;
}
 
- (void)cl_removeFooterRefresh {
    self.cl_tableView.mj_footer = nil;
}
 
@end

完成了!!! 現(xiàn)在封裝好了一個屬于我們自己的TableViewController啦.

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妒蔚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子月弛,更是在濱河造成了極大的恐慌肴盏,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帽衙,死亡現(xiàn)場離奇詭異菜皂,居然都是意外死亡,警方通過查閱死者的電腦和手機厉萝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門恍飘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谴垫,你說我怎么就攤上這事章母。” “怎么了弹渔?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵胳施,是天一觀的道長溯祸。 經(jīng)常有香客問我肢专,道長,這世上最難降的妖魔是什么焦辅? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任博杖,我火速辦了婚禮,結果婚禮上筷登,老公的妹妹穿的比我還像新娘剃根。我一直安慰自己,他們只是感情好前方,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布狈醉。 她就那樣靜靜地躺著廉油,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苗傅。 梳的紋絲不亂的頭發(fā)上抒线,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機與錄音渣慕,去河邊找鬼嘶炭。 笑死,一個胖子當著我的面吹牛逊桦,可吹牛的內(nèi)容都是我干的眨猎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼强经,長吁一口氣:“原來是場噩夢啊……” “哼睡陪!你這毒婦竟也來了?” 一聲冷哼從身側響起夕凝,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤宝穗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后码秉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逮矛,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年转砖,在試婚紗的時候發(fā)現(xiàn)自己被綠了须鼎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡府蔗,死狀恐怖晋控,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情姓赤,我是刑警寧澤赡译,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站不铆,受9級特大地震影響蝌焚,放射性物質發(fā)生泄漏。R本人自食惡果不足惜誓斥,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一只洒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劳坑,春花似錦毕谴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽循帐。三九已至,卻和暖如春舀武,著一層夾襖步出監(jiān)牢的瞬間惧浴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工奕剃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衷旅,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓纵朋,卻偏偏與公主長得像柿顶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子操软,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容