1. 程式人生 > >iOS MVVM模式總結

iOS MVVM模式總結

       MVVM模式中,ViewModel的作用是加工原來MVC模式中Controller或者Model中的根據業務場景要處理的資料,即根據業務場景處理加工Model資料,然後返回給Controller,相當於一箇中間轉化層,ViewModel的資料結構與Model的資料結構比較相似,因為是Model根據業務場景的一個轉化。是處理需要展示的資料(包括根據業務需要處理的資料,還有比如網路請求資料,比如資料轉換等等),然後將加工得到的資料給ViewController。因此ViewModel一般要引入Model的標頭檔案,在ViewModel裡面進行邏輯加工和資料處理的結果返回給ViewController。所以,ViewController裡面也要引入ViewModel

的標頭檔案,用來接收ViewModel處理的結果。ViewModel只會進行資料處理,因此不會包含UIKit的處理,不會引入UIKit的任何標頭檔案。

        Model不再像MVC那樣直接與ViewController打交道,而是與ViewModel打交道,ViewModel通過Block或者屬性將處理Model的結果返回給ViewController。

        讓我們看一個簡單的 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

Cool!現在我們假設我們有一個 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。現在來看看我們如何用一個 View Model 來增強它。

@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 的實現大概如下:

@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

Cool!我們已經將 viewDidLoad 中的表示邏輯放入我們的 View Model 裡了。此時,我們新的 viewDidLoad 就會非常輕量:

- (void)viewDidLoad {

[super viewDidLoad];

self.nameLabel.text = self.viewModel.nameText;

self.birthdateLabel.text = self.viewModel.birthdateText;

}

所以,如你所見,並沒有對我們的 MVC 架構做太多改變。還是同樣的程式碼,只不過移動了位置。它與 MVC 相容,帶來更輕量的 View Controllers。