緒論
以前在項目中大家都很喜歡使用的MVC模式,MVC即Model-VIew-Controller。他是1970年代被引入到軟件設計大眾的。MVC模式致力于關注點的切分,這意味著model和controller的邏輯是不與用戶界面(View)掛鉤的。因此,維護和測試程序變得更加簡單容易。
MVC
MVC設計模式將應用程序分離為3個主要的方面:Model,View和Controller。
- Model
Model代表了描述業(yè)務路邏輯,業(yè)務模型、數(shù)據(jù)操作、數(shù)據(jù)模型的一系列類的集合。這層也定義了數(shù)據(jù)修改和操作的業(yè)務規(guī)則。- View
View代表了UI組件,像CSS,jQuery,html等。他只負責展示從controller接收到的數(shù)據(jù)。也就是把model轉化成UI。- Controller
Controll負責處理流入的請求。它通過View來接受用戶的輸入,之后利用Model來處理用戶的數(shù)據(jù),最后把結果返回給View。Controll就是View和Model之間的一個協(xié)調者。
MVVM:
MVVM是MVC思想的完全變革。它是將“數(shù)據(jù)模型數(shù)據(jù)雙向綁定”的思想作為核心,因此在View和Model之間沒有聯(lián)系,通過ViewModel進行交互,而且Model和ViewModel之間的交互是雙向的,因此視圖的數(shù)據(jù)的變化會同時修改數(shù)據(jù)源,而數(shù)據(jù)源數(shù)據(jù)的變化也會立即反應到View上。
- 用戶和View交互。
- View和ViewModel是多對一關系。意味著一個ViewModel只映射多個View。
- View持有ViewModel的引用,但是ViewModel沒有任何View的信息。
- View 和ViewModel之間有雙向數(shù)據(jù)綁定關系。
為什么使用MVVM
在 iOS 上使用 MVVM 的動機,就是它能減少 View Controller 的復雜性并使得表示邏輯更易于測試。通過一些例子,我們將看到它如何達到這些目標。
- MVVM 可以兼容你當下使用的 MVC 架構。
- MVVM 增加你的應用的可測試性。
- MVVM 配合一個綁定機制效果最好。
注:MVVM 基本上就是 MVC 的改進版,所以很容易就能看到它如何被整合到現(xiàn)有使用典型 MVC 架構的應用中。讓我們看一個簡單的 Person Model 以及相應的 View Controller:
@interface Person : NSObject
- (instancetype)initwithSalutation:(NSString *)salutation firstName:(NSString *)firstName lastName:(NSString *)lastName birthdate:(NSDate *)birthdate;
@property (nonatomic, readonly) NSString *salutation;
@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;
@property (nonatomic, readonly) NSDate *birthdate;
@end
接著我們去創(chuàng)建一個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];
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"EEEE MMMM d, yyyy"];
self.birthdateLabel.text = [dateFormatter stringFromDate:model.birthdate];
}
以上就是標準的 MVC。現(xiàn)在來看看我們如何用一個 View Model 來增強它。首先創(chuàng)建一個PersonViewModel。
@interface PersonViewModel : NSObject
- (instancetype)initWithPerson:(Person *)person;
@property (nonatomic, readonly) Person *person;
@property (nonatomic, readonly) NSString *nameText;
@property (nonatomic, readonly) NSString *birthdateText;
@end
View Model 的具體實現(xiàn)大概如下:
@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];
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"EEEE MMMM d, yyyy"];
_birthdateText = [dateFormatter stringFromDate:person.birthdate];
return self;
}
@end
此時的我們已經(jīng)將 viewDidLoad 中的表示邏輯放入我們的 View Model 里了。此時,我們新的 viewDidLoad 就會非常輕量:
- (void)viewDidLoad {
[super viewDidLoad];
self.nameLabel.text = self.viewModel.nameText;
self.birthdateLabel.text = self.viewModel.birthdateText;
}
因此,MVVM并沒有對我們的 MVC 架構做太多改變。還是同樣的代碼,只不過移動了位置。它與 MVC 兼容,帶來更輕量的 View Controllers。