首先我們來建立一個項目,以MVC模式和MVVM模式分別展示一個簡單tableview.
1.AppGeneral:通用類
a.Base:基類(整個框架的基類,使用需要繼承)
b.Categories : 公共擴(kuò)展類 (就是一些常用的類別)
c.Macro:宏定義類 (就是整個應(yīng)用會用到的宏定義)
1):AppMacro.h -- app項目的相關(guān)宏定義
2):NotificationMacro.h -- 通知相關(guān)的宏定義
2):ApiMacro.h -- 項目中測試環(huán)境和生產(chǎn)環(huán)境所有接口路徑的宏定義
d.Models: 公共Model (公用的一些數(shù)據(jù)模型)
e.Utils:項目的相關(guān)工具類(比如類似數(shù)據(jù)請求等工具類)
f.Views:公共View (封裝的一些常用的View)
2.Main:項目中主要的東西(如AppDelegate,main.m)
3.Modules:模塊 (如首頁模塊,發(fā)現(xiàn)模塊,我的模塊等)
4.Resource:這里放置的是工程所需的一些資源(Fonts 字體,Images 圖片,Sounds 聲音,Videos 視頻)
5.Vendors : 第三方的類庫/SDK,(UMeng、baiduMapSDK等等)斗锭。
接下來進(jìn)入正題
1.MVC模式
@interface ProductModel : NSObject
@property (copy, nonatomic) NSString *desc; //描述
@end
@interface ProductCell : UITableViewCell
@property (strong, nonatomic) ProductModel *productModel;
+ (instancetype)cellForTableView:(UITableView *)tableView;
@end
@interface ProductCell ()
@property (strong, nonatomic) UILabel *descLbl;
@end
@implementation ProductCell
+ (instancetype)cellForTableView:(UITableView *)tableView
{
NSString *identify = @"ProductCell";
ProductCell *cell = [tableView dequeueReusableCellWithIdentifier:identify];
if (nil == cell) {
cell = [[ProductCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identify];
}
return cell;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.descLbl = [[UILabel alloc] init];
[self.contentView addSubview:self.descLbl];
}
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
[self.descLbl mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
}];
}
-(void)setProductModel:(ProductModel *)productModel
{
self.descLbl.text = productModel.desc;
}
@end
@interface ProductsVC ()<UITableViewDelegate,UITableViewDataSource>
@property (strong, nonatomic) UITableView *productListTableView;
@property (strong, nonatomic) NSMutableArray *productsArray;
@end
@implementation ProductsVC
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
[self setupUILayout];
[self requestData];
}
-(void)setupUI
{
self.productListTableView = [[UITableView alloc] init];
self.productListTableView.delegate = self;
self.productListTableView.dataSource = self;
[self.view addSubview:self.productListTableView];
}
-(void)setupUILayout
{
[self.productListTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view);
make.top.equalTo(self.view);
make.right.equalTo(self.view);
make.bottom.equalTo(self.view);
}];
}
-(void)requestData
{
[NetWorkManager requestWithType:HttpRequestTypeGet withUrlString:@"/test" withParaments:@{@"page":@"1"} withSuccessBlock:^(NSDictionary *object) {
if ([[object valueForKey:@"success"] boolValue]) {
self.productsArray = [ProductModel mj_objectArrayWithKeyValuesArray:[object valueForKey:@"data"]];
[self.productListTableView reloadData];
}else{
NSLog(@"%@",[object valueForKey:@"errorMsg"]);
}
} withFailureBlock:^(NSError *error) {
NSLog(@"系統(tǒng)忙,請稍后再試");
} progress:^(float progress) {
}];
}
#pragma mark-- tableDelegate,tableDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.productsArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ProductCell *cell = [ProductCell cellForTableView:tableView];
ProductModel *productModel = self.productsArray[indexPath.row];
cell.productModel = productModel;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
}
#pragma mark-- 懶加載
-(NSMutableArray *)productsArray
{
if (_productsArray==nil) {
_productsArray = [NSMutableArray array];
}
return _productsArray;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
這就完成了一個非常簡單列表的MVC模式,當(dāng)然,隨著頁面的復(fù)雜程度,你會發(fā)現(xiàn)控制器會越來越臃腫,這就是MVC模式非常大的一個弊端.
最后我們來看看MVVM+RAC模式是怎樣完成這么一個簡單的列表頁面(這里就不細(xì)講RAC的使用了) cell和model代碼不變,變的是控制器里面的代碼和新增的一個vm
@interface ProductViewModel : NSObject<UITableViewDataSource>
//請求命令
@property (strong, nonatomic) RACCommand *reuqesCommand;
//模型數(shù)組
@property (strong, nonatomic) NSArray *modelArray;
@end
@implementation ProductViewModel
- (instancetype)init
{
if (self = [super init]) {
[self initialBind];
}
return self;
}
-(void)initialBind
{
_reuqesCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[NetWorkManager requestWithType:HttpRequestTypePost withUrlString:@"/test" withParaments:@{@"page":@"1"} withSuccessBlock:^(NSDictionary *object) {
if ([[object valueForKey:@"success"] boolValue]) {
// 請求成功調(diào)用
// 把數(shù)據(jù)用信號傳遞出去
[subscriber sendNext:[ProductModel mj_objectArrayWithKeyValuesArray:[object valueForKey:@"data"]]];
[subscriber sendCompleted];
}else{
NSLog(@"%@",[object valueForKey:@"errorMsg"]);
}
} withFailureBlock:^(NSError *error) {
} progress:^(float progress) {
}];
return nil;
}];
}];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.modelArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ProductCell *cell = [ProductCell cellForTableView:tableView];
ProductModel *productModel = self.modelArray[indexPath.row];
cell.productModel = productModel;
return cell;
}
@end
@interface ProductListVC ()
@property (strong, nonatomic) UITableView *productListTableView;
@property (strong, nonatomic) ProductViewModel *productViewModel;
@end
@implementation ProductListVC
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
[self setupUILayout];
[self bindViewModel];
}
-(void)setupUI
{
self.productListTableView = [[UITableView alloc] init];
self.productListTableView.dataSource = self.productViewModel;
[self.view addSubview:self.productListTableView];
}
-(void)setupUILayout
{
[self.productListTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view);
make.top.equalTo(self.view);
make.right.equalTo(self.view);
make.bottom.equalTo(self.view);
}];
}
-(void)bindViewModel
{
//執(zhí)行請求
RACSignal *requesSiganl = [self.productViewModel.reuqesCommand execute:nil];
//獲取請求數(shù)據(jù)
[requesSiganl subscribeNext:^(NSArray *x) {
self.productViewModel.modelArray = x;
[self.productListTableView reloadData];
}];
}
#pragma mark -- 懶加載
-(ProductViewModel *)productViewModel
{
if (_productViewModel==nil) {
_productViewModel = [[ProductViewModel alloc] init];
}
return _productViewModel;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end