浅谈MVC和MVVM架构模式(二)

首先我们来建立一个项目,以MVC模式和MVVM模式分别展示一个简单tableview.

Paste_Image.png

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模式

Paste_Image.png
@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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,783评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,396评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,834评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,036评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,035评论 5 362
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,242评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,727评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,376评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,415评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,463评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,140评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,734评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,809评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,028评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,521评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,119评论 2 341

推荐阅读更多精彩内容