谈谈MVC和MVVM

栏目: 编程工具 · 发布时间: 7年前

内容简介:谈谈MVC和MVVM

刚接触iOS这行时,对架构这些没什么概念,很多时候是为了实现功能,代码难免写得杂乱不堪,这5年积累让我认识到写代码简洁优雅、层次分明、思路清晰是非常重要的。

谈谈MVC

从做iOS开发开始,接触最多的就是MVC了,我对MVC的掌握是从白胡子老头的讲课中学习来的。首先我们要明确各层的职责,Model(模型层)主要是指数据模型对象,例如Person类,View(视图层)主要是指由视图控件构成的界面,Controller(控制器层)主要负责数据操作、数据在界面上呈现。单个MVC的结构图如下:

谈谈MVC和MVVM

从图中我们可以看出各层之间的通信关系以及方式,控制器对象持有了视图对象和模型对象,可以直接访问被持有对象公开的属性和方法,模型对象与视图对象之间不可进行通信,需要一个控制器对象进行间接通信,视图对象并不持有控制器对象,可通过Target-Action来进行通信,当用户操作视图时会发送Action给对应控制器(Target)处理,当控制器需要同步了解视图正在发生的事件(Should、Will、Did)时,视图会以Delegate模式来告知其设为代理的控制器发生了什么变化,视图对象也不会持有数据对象,控制器对象可以将数据对象的属性赋值给视图对象的属性,也可以通过代理模式(DataSource)从设为代理的控制器中实现代理方法返回所需数据,数据对象不会持有视图对象和控制器对象,数据对象发生变化时,控制器对象如需了解,可以通过通知方式(Notification、KVO)来通信,视图对象也可以接收通知,但是违背MVC!(注意:Cell持有Model,也是违背MVC的!)多个MVC配合的结构图如下:

谈谈MVC和MVVM

从图中我们可以看出,一个MVC可以作为另一个MVC的子视图部分,某些数据对象之间会发生通信(持有),可能存在全局共享数据对象或者一个数据对象拆分成多个子数据对象来供子MVC使用。以下为多个MVC错乱配合的结构图(难以调试、无法模块化):

谈谈MVC和MVVM

谈谈MVVM

对于遵从MVC架构的复杂模块而言,控制器中代码会变得很臃肿,单元测试十分困难,为了解决这个问题,提出了一种新的架构MVVM,相比而言前者更为普及,更容易接受。单个MVVM的结构图如下:

谈谈MVC和MVVM

从图中我们看出,MVVM架构将UIView和UIViewController统一归为View(视图层),UIView与UIViewController之间仍是MVC架构中的通信关系,View中的UIViewController会持有ViewModel,View中的UIView会跟ViewModel在UIViewController中利用KVO/ReactiveCocoa实现数据和用户行为绑定,当用户操作界面发起数据变化时,ViewModel会进行相应业务逻辑处理并将新数据更新到界面上,ViewModel持有Model,负责业务逻辑处理后Model数据的更新,Model与ViewModel之间也存在数据绑定,可在其中进行数据加工处理,当Model数据变化时ViewModel数据也要相应变化。

RAC实践MVVM

Demo地址是 https://github.com/monkiyang/ReactiveCocoaGo ,关键代码摘录如下:

// MKMainViewController.m
...

- (void)learnRACCommand {
    //点击登录按钮处理登录请求
    //RACCommand绑定UI响应事件
    self.loginView.loginButton.rac_command = self.userViewModel.loginCommand;
    
    //RAC()、RACObserve()绑定控件与ViewModel
    RAC(self.loginView.statusLabel, text) = RACObserve(_userViewModel, status);
    RAC(self.infoView.nicknameLabel, text) = RACObserve(_userViewModel, nickname);
    RAC(self.infoView.genderLabel, text) = RACObserve(_userViewModel, gender);
}

...
// MKUserViewModel.m
...

- (void)bindModel {
    //RAC()、RACObserve()绑定ViewModel与Model
    RAC(self, nickname) = [RACObserve(_userModel, nickname) map:^id(NSString *value) {
        if (value.length == 0) {
            return value;
        }
        return [NSString stringWithFormat:@"My nickname is %@, ", value];
    }];
    RAC(self, gender) = [RACObserve(_userModel, gender) map:^id(NSString *value) {
        if (value.length == 0) {
            return value;
        }
        return [NSString stringWithFormat:@"I'm %@.", value];
    }];
}

...

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程精粹

编程精粹

Steve Maguire / 人民邮电出版社 / 2009.2 / 45.00元

编写高质量的、没有bug的程序,是每位程序员所追求的目标。但随着软件规模越来越大,功能日趋复杂,这一目标变得越来越困难。 本书揭示了微软公司应对质量挑战、开发出世界级代码的技术内幕,作者在自己不断探索、实践和思考的基础上,系统总结了多年来指导微软各团队的经验,将其凝聚为许多切实可行的编程实践指导,可谓字字珠玑。正因如此,本书被公认为与《代码大全》齐名的编程技术名著,曾于1993年荣获有软件开......一起来看看 《编程精粹》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具