avatar

Catalog
iOS架构设计05-MVVM

相信大家都听过这种架构,我们来看下图

跟我们上篇文章说的MVP挺像的,中间的Presenter,变成了ViewModel
这种架构其实也是三种角色

  • Model

  • View

  • ViewModel

这种架构,跟MVP的共同点:

  • 都能达到ViewController的瘦身,
  • ViewModel的隔离,

MVP不同点

  • 双向绑定

就是我们的View一旦监听到了ViewModel里的数据变化可以自动更新,一提到MVVM我们大家肯定都会想到RAC这个框架,由于这个框架比较重,为了方便介绍这种架构,我选择另一种方案,KVO,这里我们要是自己写的话很麻烦,我就直接用Facebook开源的KVOController大家可以上GitHub去下载

下面我们来看下实例

我们还是沿用上篇文章的Demo来进行修改,首先我们把Presenter删掉,然后新建我们的ViewModelPresenter里的大部分逻辑还是可以copyViewModel里的,还有一点就是因为ViewModel要绑定Model所以会把Model的属性都赋值给ViewModel,然后View只要监听ViewModel里的属性变化来改变自己就行了

Code
1
2
3
@interface XXAppViewModel : NSObject
- (instancetype)initWithController:(UIViewController *)controller;
@end
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@interface XXAppViewModel() <XXAppViewDelegate>
@property (weak, nonatomic) UIViewController *controller;
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *image;
@end

@implementation XXAppViewModel

- (instancetype)initWithController:(UIViewController *)controller
{
if (self = [super init]) {
self.controller = controller;

// 创建View
XXAppView *appView = [[XXAppView alloc] init];
appView.frame = CGRectMake(100, 100, 100, 150);
appView.delegate = self;
appView.viewModel = self;
[controller.view addSubview:appView];

// 加载模型数据
XXApp *app = [[XXApp alloc] init];
app.name = @"QQ";
app.image = @"QQ";

// 设置数据完成绑定
self.name = app.name;
self.image = app.image;
}
return self;
}

#pragma mark - XXAppViewDelegate
- (void)appViewDidClick:(XXAppView *)appView
{
NSLog(@"viewModel 监听了 appView 的点击");
}

接下来我们修改下ViewController,把Presenter换成ViewModel

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
@interface ViewController ()
@property (strong, nonatomic) XXAppViewModel *viewModel;
@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.viewModel = [[XXAppViewModel alloc] initWithController:self];
}

@end

最后我们来看下我们的View的修改的地方,因为要和ViewModel进行双向绑定,所以我们要有个ViewModel对象

Code
1
@property (weak, nonatomic) XXAppViewModel *viewModel;

然后我们在setViewModel的时候做属性监听这里我们用的KVOController

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)setViewModel:(XXAppViewModel *)viewModel
{
_viewModel = viewModel;

__weak typeof(self) weakSelf = self;
[self.KVOController observe:viewModel keyPath:@"name" options:NSKeyValueObservingOptionNew block:^(id _Nullable observer, id _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
weakSelf.nameLabel.text = change[NSKeyValueChangeNewKey];
}];

[self.KVOController observe:viewModel keyPath:@"image" options:NSKeyValueObservingOptionNew block:^(id _Nullable observer, id _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
weakSelf.iconView.image = [UIImage imageNamed:change[NSKeyValueChangeNewKey]];
}];
}

这样我们就完成了双向绑定,只要我们的ViewModel里的数据变化了,View就会监听到改动从而更新自己

总结

Demo只是很简单的一种阐述,很多公司里的都是MVVM+RAC,有时间我也会开个RAC的专栏来记录下这个框架的使用,还是那句话,架构这种东西没有唯一,选择适合自己的就行。

明天我们来说说分层架构

点此进入我的博客也会同步更新

One More Thing

点击查看 2020—课程列表 全网IT各种资源有需求的可以微我,或者你喜欢的课程都可以给我发链接剩下的我来搞定

喜欢的朋友可以扫描关注我的公众号(多多点赞,多多打赏,您的支持是我写作的最大动力)关注有福利可以使用免费梯子自由上网

iOS_DevTips

Author: 木子召
Link: https://lizhaobomb.github.io/2020/03/10/iOS%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A105-MVVM/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶

Comment