美文网首页面试合集
[iOS][MVVM]理解MVVM

[iOS][MVVM]理解MVVM

作者: 未来行者 | 来源:发表于2019-05-10 23:25 被阅读0次

    前言

    MMVM这个概念,相信很多人都听过,但很多人估计和我一样,没真正去理解和运用过,对它只是一知半解而已.最近因为做了新项目,有意向引入MVVM的模式,因此去进行了一些研究.研究之后,才发现涉及的点还是比较多的.

    为什么要用MVVM

    传统的MVC对于大项目而言,如果编码不规范,必定会造成VC臃肿,单元测试难度大,以及代码结构(不是风格,风格因人而异)不统一的问题.而MVVM便解决了这些问题.

    • 为VC解耦.
    • 利于测试.
    • 利于统一整体代码结构.
    MVVM说明

    各个模块的定义.

    M : 表示Model,但这个Model不单纯是一个只保存属性的Model,而是将数据请求,加工,持久化结合起来的model,也可以称作是胖model.一般而言,model只是一个属性存储的东西,但在MVVM中,它的功能丰富了许多,正因为如此,分担了VC部分逻辑,而且更符合它的意义(提供可用数据).
    这里举一个登录的例子,这个TLoginDataModel就代表一个Model,它的作用是发起登录请求然后将结果包装后回调.

    #import <Foundation/Foundation.h>
    @interface TLoginDataModel : NSObject
    // 提供一个登录请求方法
    - (void)requestToLoginWithParam:(id)param completionBlock:(void(^)(id responseObject,NSError *error))block;
    @end
    

    V : 表示View,这个view同时也包含了vc,因为在iOS中,VC其实可以算作其他view的容器,因为它本身提供了一个最基本的view,view会和ViewModel进行绑定.
    下面是一个登录界面,输入账号密码之后点击登录,viewModel发起请求,会把Model请求下来包装好的数据进行显示,也就表示登录成功了.

    // .h文件
    @class TLoginViewModel;
    @interface TLoginView : UIView
    // 提供一个绑定ViewModel的方法
    - (void)bindViewModel:(TLoginViewModel *)viewModel;
    @end
    // .m文件
    @interface TLoginView()
    @property (nonatomic, strong) UIButton *button;
    @property (nonatomic, strong) UILabel *label1;
    @property (nonatomic, strong) UILabel *label2;
    @property (nonatomic, strong) UITextField *textF1;
    @property (nonatomic, strong) UITextField *textF2;
    @property (nonatomic, strong) TLoginViewModel *viewModel;
    @end
    

    VM : 表示ViewModel,它是View和Model之间的桥梁,让View和Model不进行直接耦合,通过ViewModel来传递数据.
    具体过程是:ViewModel绑定Model,监听数据变化;然后View绑定ViewModel,当数据发生变化时,ViewModel会通知View发生了变化,从而更新UI显示.

        // 在loginViewController内
    
        self.model = [TLoginDataModel new];
        self.viewModel = [TLoginViewModel new];
        
        // viewModel 绑定model
        [self.viewModel bindDataModel:self.model];
        
        // view 绑定 viewModel
        [self.loginView bindViewModel:self.viewModel];
    
        // 监听网络回调
        Weakify(self);
        // 初始化监听,模仿的FBKVOController
        self.kvoAgent = [[TObserverAgent alloc] init];
        [self.kvoAgent t_addObserverForTarget:self.viewModel keyPath:@t_keypath(self.viewModel,command.result) handler:^(NSDictionary *change, id target, NSString *keyPath) {
            Strongify(self);
            // 请求回来之后result改变,得到回调的数据
            TCommandResult *newValue = change[NSKeyValueChangeNewKey];
            [self.resultLabel setText:newValue.responseObject];
        }];
    

    这里实际上是监听了viewModelcommand.result属性,在TLoginViewModel.m中,我们可以看到它的回调方式如下:

    - (void)initItems{
        Weakify(self);
        // 通过TCommand进行数据传递
        self.command = [[TCommand alloc] initWithRequestBlock:^(id param, CompletionHandler completionHandler) {
            Strongify(self);
            [self.dataModel requestToLoginWithParam:param completionBlock:^(id responseObject, NSError *error) {
                SAFE_BLOCK(completionHandler,error,responseObject);
            }];
        }];
    }
    // 绑定Model
    - (void)bindDataModel:(TLoginDataModel *)dataModel{
        self.dataModel = dataModel;
    }
    

    这里TCommand的作用类似于RAC里的RACCommand,作用是执行某个操作,操作完成后,把请求的数据转发出去.我们把Model包装的数据再次用TCommandResult包装了一下,这样外部就可以KVOcommand.result来更新UI了.

    这样就完成了一个简单的MVVM模式登录demo,这里也没有运用RAC这个重型的框架,只是根据需要进行了适当工具封装便达到了同样的效果.其实MVVM重点就在于View和Model的双向绑定,如何优雅的解决它,就是RAC的价值体现.

    但本人并不是很喜欢用它,所以后续会自己实现一些比较优雅的方法来实现同样的效果.

    demo地址

    相关文章

      网友评论

        本文标题:[iOS][MVVM]理解MVVM

        本文链接:https://www.haomeiwen.com/subject/ajizoqtx.html