相信大家都听过这种架构,我们来看下图
![]()
跟我们上篇文章说的MVP挺像的,中间的Presenter,变成了ViewModel
这种架构其实也是三种角色
这种架构,跟MVP的共同点:
- 都能达到
ViewController的瘦身,
View和Model的隔离,
跟MVP不同点
就是我们的View一旦监听到了ViewModel里的数据变化可以自动更新,一提到MVVM我们大家肯定都会想到RAC这个框架,由于这个框架比较重,为了方便介绍这种架构,我选择另一种方案,KVO,这里我们要是自己写的话很麻烦,我就直接用Facebook开源的KVOController大家可以上GitHub去下载
下面我们来看下实例
我们还是沿用上篇文章的Demo来进行修改,首先我们把Presenter删掉,然后新建我们的ViewModel,Presenter里的大部分逻辑还是可以copy到ViewModel里的,还有一点就是因为ViewModel要绑定Model所以会把Model的属性都赋值给ViewModel,然后View只要监听ViewModel里的属性变化来改变自己就行了
1 2 3
| @interface XXAppViewModel : NSObject - (instancetype)initWithController:(UIViewController *)controller; @end
|
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
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对象
1
| @property (weak, nonatomic) XXAppViewModel *viewModel;
|
然后我们在setViewModel的时候做属性监听这里我们用的KVOController
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的专栏来记录下这个框架的使用,还是那句话,架构这种东西没有唯一,选择适合自己的就行。
明天我们来说说分层架构
点击查看 2020—课程列表 全网IT各种资源有需求的可以微我,或者你喜欢的课程都可以给我发链接剩下的我来搞定
喜欢的朋友可以扫描关注我的公众号(多多点赞,多多打赏,您的支持是我写作的最大动力)关注有福利可以使用免费梯子自由上网
![iOS_DevTips iOS_DevTips]()