最近看到新浪微博上以及iOS開發的論壇裏面談到MVVM設計模式,所謂MVVM就是Model-View-ViewModel的縮寫,關於MVVM的概念,這裏我不想過多的介紹,有不少介紹的很詳細的博文,這裏咱們直奔主題,談一談MVVM如何利用到項目中去。react
首先咱們在創建項目中的時候可分爲以下模塊,Model,View,ViewModel,Controller.設計模式
Model: 數據模型,用來處理數據網絡
View: 視圖類,用來作界面設計框架
ViewModel: 用來寫界面以及邏輯函數
Controller: 控制器類,用來處理控制器之間的邏輯工具
這裏有人確定會問了,MVVM不是Model-View-ViewModel嗎,爲何還會有控制器,這裏的控制器是用來爲頁面跳轉以及加載提供入口的,以及將控制器邏輯利用代理和代碼塊的方式讓ViewModel來實現。光說不練假把式,先來看一看文件夾吧。測試
和我前面說的同樣,模塊被分爲了4部分,這樣咱們可使咱們的controller再也不那麼(胖),與傳統的MVC相比,文件反而多了,但是這樣一來,控制器裏面的代碼就減小了不少,只須要調用對應的功能的函數就能夠了。接下來再看看viewModel裏面寫的什麼atom
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import "WeatherView.h" #import "weatherModel.h" @interface WeatherViewModel : NSObject @property (nonatomic, strong) WeatherView *view; /**< 用來與controller裏面的View匹配*/ @property (nonatomic, strong) weatherModel *model; @property (nonatomic, strong) UITableView *myTableView; - (instancetype)initWithFrame:(CGRect)frame;
- (void)didSelect; @end
#import "WeatherViewModel.h" #import "WeatherTableViewCell.h" #import "weatherModel+Request.h" static NSString * const kApiUrl = @"www.baidu.com"; @implementation WeatherViewModel - (instancetype)initWithFrame:(CGRect)frame { self = [super init]; if (self) { [self initWithModel]; _view = [[WeatherView alloc]initWithFrame:frame]; [_view addSubview:self.myTableView]; } return self; } - (void)initWithModel { [weatherModel requestWithURL:kApiUrl AndParmars:@{} WithSuccessBlock:^(id responseObject) { self.model = responseObject[@"data"]; } WithFailBlock:^(id error) { }]; } - (UITableView *)myTableView { if (!_myTableView) { _myTableView = [[UITableView alloc]initWithFrame:_view.frame style:UITableViewStylePlain]; _myTableView.tableFooterView = [[UIView alloc]init]; _myTableView.backgroundColor = [UIColor yellowColor]; } return _myTableView; }
- (void)didSelect {
NSLog(@"點擊了cell");spa
}設計
這裏我直接把UI也寫了進來,到了這裏各位可能要問了,不是說是viewModel嗎,並且這個類是繼承NSObject的,爲何要在這裏面寫UI。沒錯,在我看來它也只是一個工具類,可個人目的是想讓controller變得更簡,簡到咱們看一個controller的時候只須要知道它有哪些功能,能作什麼就好。其餘的所有交給viewmodel去處理吧。咱們能夠把網絡請求還有一些邏輯處理全都放進來,極大的下降代碼的耦合度。
接下來咱們再來看看controller裏面寫什麼,
#import "WeatherViewController.h" #import "WeatherViewModel.h" #import "WeatherTableViewCell.h" @interface WeatherViewController ()<UITableViewDataSource,UITableViewDelegate> { WeatherViewModel *viewModel; /**< 當前控制器的viewModel*/ } @end @implementation WeatherViewController - (void)viewDidLoad { [super viewDidLoad]; [self setUp]; // Do any additional setup after loading the view. } - (void)setUp { self.title = @"天氣測試"; viewModel = [[WeatherViewModel alloc] initWithFrame:self.view.bounds]; viewModel.myTableView.delegate = self; viewModel.myTableView.dataSource = self; [self.view addSubview:viewModel.view]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 20; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *reuseIdentifier = @"reuseIdentifier"; WeatherTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; if (!cell) { cell = [[WeatherTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; cell.textLabel.text = @"it is a test"; } return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [viewModel didSelect]; }
controller裏面不須要寫UI,直接把viewModel裏面所定義的view加在當前控制器上view上就能夠了。實現一些必要的代理,這裏大夥兒必定會想,爲何UI都寫在了viewmodel裏,還要把代理方法寫在controller裏,這裏我嘗試了在viewmodel裏面寫,可是會存在cell的複用問題。若是您有好的解決方法,請您給我留言,很是感謝。
關於如何將控制器的邏輯交給viewmodel,能夠有代理,block,或者通知,固然,目前最完美的當屬'ReactiveCocoa了,有關reactiveCocoa框架的介紹也有不少,這裏有一篇比較好的文章 http://nathanli.cn/2015/08/27/reactivecocoa2-%E6%BA%90%E7%A0%81%E6%B5%85%E6%9E%90/。
以上是關於MVVM的一些我的理解,理解的過程中確定存在有些不足,但願在之後的使用過程中能有更好的總結。