Introduction to MVVM Architecture Design and team collaboration in iOS

Source: Internet
Author: User

Introduction to MVVM Architecture Design and team collaboration in iOS

The ViewModel layer is the binder of the View and Model layers. It is an excellent place for placing user input verification logic, View display logic, initiating network requests and various other code. To put it bluntly, the business logic and page logic of the original ViewController layer are stripped out and placed on the ViewModel layer.

The View layer is the ViewController layer. Its task is to obtain data from the ViewModel layer and then display it.

Have you ever heard of MVC? Some people call it Massive View Controller (heavyweight View Controller), which is what we felt at that time. I don't want to introduce the shameful details, but to be honest, if I have to do it again, I will definitely make different decisions.

I will modify a key architecture and bring it into the various applications I have been developing since then, that is, replacing Model-View-Controller with a schema called Model-View-ViewModel.

So what is MVVM? Instead of focusing on explaining the origins of MVVM, let's look at how a typical iOS is built and learn about MVVM from there:

We can see a typical MVC setting. The Model presents data and the View displays the user interface, while the View Controller adjusts the interaction between the two. Cool!

Although View and View Controller are technically different components, they are almost always hand in hand and paired. When do you see that a View can be paired with different View controllers? Or vice versa? So why not normalize their connections?

This more accurately describes the MVC code you may have written. However, it does not do much to solve the problem of increasing heavyweight view controllers in iOS applications. In typical MVC applications, many logics are placed in View Controller. Some of them do belong to the View Controller, but more are the so-called "presentation logic". In MVVM terminology, is something that converts the Model data into a View that can be presented, for exampleNSDateConvert to a formattedNSString.

Some things are missing in our illustration, which allow us to put all the representation logics in. We plan to call it "View Model" -- It is located between View/Controller and Model:

It looks much better! This graphic accurately describes what MVVM is: an enhanced version of MVC. We formally connect the view and Controller and move the representation logic from the Controller to a new object, that is, View Model. MVVM sounds complicated, but it is essentially a well-optimized MVC Architecture, which you are already familiar.

Now we know what MVVM is, but why do we want to use it? The motivation for using MVVM on iOS is that it can reduce the complexity of View Controller and make the presentation logic easier to test. Through some examples, we will see how it achieves these goals.

I hope you can take the following three points after reading this article:

  • MVVM can be compatible with the MVC Architecture you are currently using.
  • MVVM increases the testability of your application.
  • MVVM works best with a binding mechanism.

    As we have seen before, MVVM is basically the optimized version of MVC, so it is easy to see how it is integrated into existing applications using the typical MVC Architecture. Let's look at a simplePersonModel and corresponding 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! Now let's assume that we havePersonViewController, InviewDidLoad, You only needmodelSet some labels for properties.

    - (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];}

    This is all straightforward, standard MVC. Now let's take a look at how we can use a View Model to enhance it.

    @interface PersonViewModel : NSObject- (instancetype)initWithPerson:(Person *)person;@property (nonatomic, readonly) Person *person;@property (nonatomic, readonly) NSString *nameText;@property (nonatomic, readonly) NSString *birthdateText;@end

    The implementation of our View Model is roughly as follows:

    @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! We haveviewDidLoadPut the representation logic in our View Model. At this time, our newviewDidLoadIt will be very lightweight:

    - (void)viewDidLoad {    [super viewDidLoad];    self.nameLabel.text = self.viewModel.nameText;    self.birthdateLabel.text = self.viewModel.birthdateText;}

    So, as you have seen, we have not made too many changes to our MVC Architecture. The Code is the same, but the location is moved. It is compatible with MVC and brings a lighter amount of View Controllers.

    Testable, huh? What is it? Well, View Controller is notoriously difficult to test because they have done too many things. In MVVM, we try to move as much code as possible into the View Model. It is much easier to test the View Controller, because they do not do a lot of things, and the View Model is also very easy to test. Let's take a look:

    SpecBegin(Person)    NSString *salutation = @"Dr.";    NSString *firstName = @"first";    NSString *lastName = @"last";    NSDate *birthdate = [NSDate dateWithTimeIntervalSince1970:0];    it (@"should use the salutation available. ", ^{        Person *person = [[Person alloc] initWithSalutation:salutation firstName:firstName lastName:lastName birthdate:birthdate];        PersonViewModel *viewModel = [[PersonViewModel alloc] initWithPerson:person];        expect(viewModel.nameText).to.equal(@"Dr. first last");    });    it (@"should not use an unavailable salutation. ", ^{        Person *person = [[Person alloc] initWithSalutation:nil firstName:firstName lastName:lastName birthdate:birthdate];        PersonViewModel *viewModel = [[PersonViewModel alloc] initWithPerson:person];        expect(viewModel.nameText).to.equal(@"first last");    });    it (@"should use the correct date format. ", ^{        Person *person = [[Person alloc] initWithSalutation:nil firstName:firstName lastName:lastName birthdate:birthdate];        PersonViewModel *viewModel = [[PersonViewModel alloc] initWithPerson:person];        expect(viewModel.birthdateText).to.equal(@"Thursday January 1, 1970");    });SpecEnd

    If we do not move this logic into the View Model, we will have to instantiate a complete View Controller and the accompanying View, and then compare the Lable value in our View. This is not only a troublesome indirect layer, but also a very fragile test. Now, we can modify the view hierarchy as needed without worrying about disrupting our unit tests. The benefits of using MVVM for testing are very clear, and even can be seen from this simple example. In the case of more complex representation logic, this benefit is more obvious.

    Note that in this simple example, the Model is immutable, so we can only specify the attribute of our View Model during initialization. For a variable Model, we also need to use some binding mechanisms so that the View Model can update its attributes when the Model behind it changes. In addition, once the Model on the View Model changes, the View attributes also need to be updated. The changes to the Model should be cascade down to enter the View through the View Model.

    On OS X, we can use Cocoa binding, but on iOS we do not have such a good configuration available. We thought of KVO (Key-Value Observation), and it did a great job. However, a simple binding requires a lot of sample code, not to mention many attributes that need to be bound. As an alternative, I personally like to use ReactiveCocoa, but MVVM does not force us to use ReactiveCocoa. MVVM is a great model. It is independent of itself, but it performs better when there is a good binding framework.

    We have covered a lot of content: the MVVM is derived from common MVC, and how they are compatible with the paradigm. We can observe the MVVM from a testable example, we can see that MVVM works better with a paired binding mechanism. If you are interested in learning

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.