首先介绍一个典型的MVC模式:
有人称之为 Massive View Controller(重量级视图控制器)
- Model 呈现数据
- View 呈现用户界面
- View Controller 调节它两者之间的交互
我们这样考虑:虽然 View 和 View Controller 是技术上不同的组件,但它们几乎总是手牵手在一起,成对的。你什么时候看到一个 View 能够与不同 View Controller 配对?
我们的MVC模式下的代码,目前并没有做太多事情来解决 iOS 应用中日益增长的重量级视图控制器的问题。在典型的 MVC 应用里,许多逻辑被放在View Controller
里。它们中的一些确实属于 View Controller
,但更多的是所谓的“表示逻辑(presentation logic)”,以 MVVM 属术语来说,就是那些将Model
数据转换为 View
可以呈现的东西的事情,例如将一个 NSDate
转换为一个格式化过的NSString
。
对于MVVM的描述,我们先来看下图:
屏幕快照 2017-10-16 下午1.52.46.png这个图解准确地描述了什么是 MVVM:一个 MVC 的增强版,我们正式连接了视图和控制器,并将表示逻辑从 Controller 移出放到一个新的对象里,即 View Model。MVVM 听起来很复杂,但它本质上就是一个精心优化的 MVC 架构,而 MVC 你早已熟悉。
下面我们就举例来看,如何使用MVVM
首先有一个Person Model
@interface Person : NSObject
@property (nonatomic, copy) NSString *salutation;
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@end
现在我们假设我们有一个 PersonViewController ,在 viewDidLoad 里,只需要基于它的 model 属性设置 Label 即可。
- (void)viewDidLoad {
[super viewDidLoad];
if (self.model.salutation.length > 0) {
self.nameLabel.text = [NSString stringWithFormat:@"%@ %@ %@", self.model.salutation, self.model.firstName, self.model.lastName];
} else {
self.nameLabel.text = [NSString stringWithFormat:@"%@ %@", self.model.firstName, self.model.lastName];
}
}
现在来看看我们如何用一个 View Model 来增强它:
@interface PersonViewModel : NSObject
- (instancetype)initWithPerson:(Person *)person;
@property (nonatomic, readonly) Person *person;
@property (nonatomic, readonly) NSString *nameText;
@end
我们的 View Model 的实现大概如下:
@implementation PersonViewModel
- (instancetype)initWithPerson:(Person *)person {
self = [super init];
if (!self) return nil;
_person = person;
if (person.salutation.length > 0) {
_nameText = [NSString stringWithFormat:@"%@ %@ %@", self.person.salutation, self.person.firstName, self.person.lastName];
} else {
_nameText = [NSString stringWithFormat:@"%@ %@", self.person.firstName, self.person.lastName];
}
return self;
}
@end
我们已经将 viewDidLoad 中的表示逻辑放入我们的 View Model 里了。此时,我们新的 viewDidLoad 就会非常轻量:
- (void)viewDidLoad {
[super viewDidLoad];
self.nameLabel.text = self.viewModel.nameText;
}
如你所见,并没有对我们的 MVC 架构做太多改变。还是同样的代码,只不过移动了位置。它与 MVC 兼容,带来更轻量的 View Controllers。
网友评论