首先我们来建立一个项目,以MVC模式和MVVM模式分别展示一个简单tableview.
1.AppGeneral:通用类
a.Base:基类(整个框架的基类,使用需要继承)
b.Categories : 公共扩展类 (就是一些常用的类别)
c.Macro:宏定义类 (就是整个应用会用到的宏定义)
1):AppMacro.h -- app项目的相关宏定义
2):NotificationMacro.h -- 通知相关的宏定义
2):ApiMacro.h -- 项目中测试环境和生产环境所有接口路径的宏定义
d.Models: 公共Model (公用的一些数据模型)
e.Utils:项目的相关工具类(比如类似数据请求等工具类)
f.Views:公共View (封装的一些常用的View)
2.Main:项目中主要的东西(如AppDelegate,main.m)
3.Modules:模块 (如首页模块,发现模块,我的模块等)
4.Resource:这里放置的是工程所需的一些资源(Fonts 字体,Images 图片,Sounds 声音,Videos 视频)
5.Vendors : 第三方的类库/SDK,(UMeng、baiduMapSDK等等)。
接下来进入正题
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(@"系统忙,请稍后再试");
} 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模式,当然,随着页面的复杂程度,你会发现控制器会越来越臃肿,这就是MVC模式非常大的一个弊端.
最后我们来看看MVVM+RAC模式是怎样完成这么一个简单的列表页面(这里就不细讲RAC的使用了) cell和model代码不变,变的是控制器里面的代码和新增的一个vm
@interface ProductViewModel : NSObject<UITableViewDataSource>
//请求命令
@property (strong, nonatomic) RACCommand *reuqesCommand;
//模型数组
@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]) {
// 请求成功调用
// 把数据用信号传递出去
[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
{
//执行请求
RACSignal *requesSiganl = [self.productViewModel.reuqesCommand execute:nil];
//获取请求数据
[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