IOS架构之MVVM.docx

上传人:b****2 文档编号:23102750 上传时间:2023-04-30 格式:DOCX 页数:10 大小:34.77KB
下载 相关 举报
IOS架构之MVVM.docx_第1页
第1页 / 共10页
IOS架构之MVVM.docx_第2页
第2页 / 共10页
IOS架构之MVVM.docx_第3页
第3页 / 共10页
IOS架构之MVVM.docx_第4页
第4页 / 共10页
IOS架构之MVVM.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

IOS架构之MVVM.docx

《IOS架构之MVVM.docx》由会员分享,可在线阅读,更多相关《IOS架构之MVVM.docx(10页珍藏版)》请在冰豆网上搜索。

IOS架构之MVVM.docx

IOS架构之MVVM

IntroductiontoMVVM

MVVM介绍

IgotmyfirstiOSjobat500pxin2011.IhadbeendoingiOScontractingforafewyearsincollege,butthiswasmyfirst,realiOSgig.IwashiredasthesoleiOSdevelopertomakethebeautifullydesignediPadapp.Inonlysevenweeks,weshippeda1.0andcontinuedtoiterate,addingmorefeaturesand,intrinsically,morecomplexitytothecodebase.

在2011年,我在500PX这家公司得到自己第一份做IOS的工作,事实上,我在大学的几年已经开始做IOS开发的一些承包工作,但是真正的做一个漂亮的IOS项目,还是从这份工作开始的。

我被聘为唯一的iOS开发者将设计精美的iPad应用程序,仅用了七个星期,我们就发布了1.0版本,然后持续不断的迭代新的功能,从本质上讲,我的代码也越来越复杂。

ItfeltattimeslikeIdidn’tknowwhatIwasdoing.Iknewmydesignpatterns–likeanygoodcoder–butIwaswaytooclosetotheproductIwasmakingtoobjectivelymeasuretheefficacyofmyarchitecturaldecisions.Ittookbringinganotherdeveloperonboardtheteamformetorealizethatwewereintrouble.

有时我感觉就像我不知道在做什么。

虽然我知道自己的设计模式——就像任何好的编程人员那样——但我太接近我在做的产品以至于不能客观地衡量我的架构决策的有效性。

当队伍中来了另外一位开发者时,我意识到我们陷入困境了。

EverheardofMVC?

MassiveViewController,somecallit.That’scertainlyhowitfeltatthetime.Iwon’tgointotheembarrassingdetails,butitsufficestosaythatifIhadtodoitalloveragain,Iwouldmakedifferentdecisions.

从没听过MVC?

有人称之为MassiveViewController(重量级视图控制器),这就是我们那时候的感觉。

我不打算介绍令人汗颜的细节,但说实在的,如果我不得不再次重来一次,我绝对会做出不同的决策。

OneofthekeyarchitecturalchangesIwouldmake,andhavemadeinappsI’vedevelopedsincethen,wouldbetouseanalternativetoModel-View-ControllercalledModel-View-ViewModel.

我会修改一个关键架构,并将其带入我从那时起就在开发的各种应用,即使用一种叫做Model-View-ViewModel的架构替换Model-View-Controller。

SowhatisMVVM,exactly?

InsteadoffocusingonthehistoricalcontextofwhereMVVMcamefrom,let’stakealookatwhatatypicaliOSapplookslikeandderiveMVVMfromthere:

所以,MVVM到底是什么?

与其专注于说明MVVM的来历,不如让我们看一个典型的iOS是如何构建的,并从那里了解MVVM:

HereweseeatypicalMVCsetup.Modelsrepresentdata,viewsrepresentuserinterfaces,andviewcontrollersmediatetheinteractionsbetweenthetwoofthem.Cool.

我们看到的是一个典型的MVC设置。

Model呈现数据,View呈现用户界面,而ViewController调节它两者之间的交互。

Cool!

Considerforamomentthat,althoughviewsandviewcontrollersaretechnicallydistinctcomponents,theyalmostalwaysgohand-in-handtogether,paired.Whenisthelasttimethataviewcouldbepairedwithdifferentviewcontrollers?

Orviceversa?

Sowhynotformalizetheirconnection?

稍微考虑一下,虽然View和ViewController是技术上不同的组件,但它们几乎总是手牵手在一起,成对的。

你什么时候看到一个View能够与不同ViewController配对?

或者反过来?

所以,为什么不正规化它们的连接呢?

ThismoreaccuratelydescribestheMVCcodethatyou’reprobablyalreadywriting.Butitdoesn’tdomuchtoaddressthemassiveviewcontrollersthattendtogrowiniOSapps.IntypicalMVCapplications,alotoflogicgetsplacedintheviewcontroller.Someofitbelongsintheviewcontroller,sure,butalotofitiswhat’scalled‘presentationlogic,’inMVVMterms–thingsliketransformingvaluesfromthemodelintosomethingtheviewcanpresent,liketakinganNSDateandturningitintoaformattedNSString.

这更准确地描述了你可能已经编写的MVC代码。

但它并没有做太多事情来解决iOS应用中日益增长的重量级视图控制器的问题。

在典型的MVC应用里,许多逻辑被放在ViewController里。

它们中的一些确实属于ViewController,但更多的是所谓的“表示逻辑(presentationlogic)”,以MVVM属术语来说,就是那些将Model数据转换为View可以呈现的东西的事情,例如将一个NSDate转换为一个格式化过的NSString。

We’remissingsomethingfromourdiagram.Somethingwherewecanplaceallofthatpresentationlogic.We’regoingtocallthisthe'viewmodel’–itwillsitbetweentheview/controllerandthemodel:

我们的图解里缺少某些东西,那些使我们可以把所有表示逻辑放进去的东西。

我们打算将其称为“ViewModel”——它位于View/Controller与Model之间:

Lookingbetter!

ThisdiagramaccuratelydescribeswhatMVVMis:

anaugmentedversionofMVCwhereweformallyconnecttheviewandcontroller,andmovepresentationlogicoutofthecontrollerandintoanewobject,theviewmodel.MVVMsoundscomplicated,butit’sessentiallyadressed-upversionoftheMVCarchitecturethatyou’realreadyfamiliarwith.

看起好多了!

这个图解准确地描述了什么是MVVM:

一个MVC的增强版,我们正式连接了视图和控制器,并将表示逻辑从Controller移出放到一个新的对象里,即ViewModel。

MVVM听起来很复杂,但它本质上就是一个精心优化的MVC架构,而MVC你早已熟悉。

SonowthatweknowwhatMVVMis,whywouldonewanttouseit?

ThemotivationbehindMVVMoniOS,forme,anyway,isthatitreducesthecomplexityofone’sviewcontrollersandmakesone’spresentationlogiceasiertotest.We’llseehowitaccomplishesthesegoalswithsomeexamples.

现在我们知道了什么是MVVM,但为什么我们会想要去使用它呢?

在iOS上使用MVVM的动机,对我来说,无论如何,就是它能减少ViewController的复杂性并使得表示逻辑更易于测试。

通过一些例子,我们将看到它如何达到这些目标。

TherearethreereallyimportantpointsIwantyoutotakeawayfromthisarticle:

MVVMiscompatiblewithyourexistingMVCarchitecture.

MVVMmakesyourappsmoretestable.

MVVMworksbestwithabindingmechanism.

此处有三个重点是我希望你看完本文能带走的:

MVVM可以兼容你当下使用的MVC架构。

MVVM增加你的应用的可测试性。

MVVM配合一个绑定机制效果最好。

Aswesawearlier,MVVMisbasicallyjustaspruced-upversionofMVC,soit’seasytoseehowitcanbeincorporatedintoanexistingappwithatypicalMVCarchitecture.Let’stakeasimplePersonmodelandcorrespondingviewcontroller:

如我们之前所见,MVVM基本上就是MVC的改进版,所以很容易就能看到它如何被整合到现有使用典型MVC架构的应用中。

让我们看一个简单的PersonModel以及相应的ViewController:

@interfacePerson:

NSObject

-(instancetype)initwithSalutation:

(NSString*)salutationfirstName:

(NSString*)firstNamelastName:

(NSString*)lastNamebirthdate:

(NSDate*)birthdate;

@property(nonatomic,readonly)NSString*salutation;

@property(nonatomic,readonly)NSString*firstName;

@property(nonatomic,readonly)NSString*lastName;

@property(nonatomic,readonly)NSDate*birthdate;

@end

Cool.Nowlet’ssaythatwehaveaPersonViewControllerthat,inviewDidLoad,justsetssomelabelsbasedonitsmodelproperty:

Cool!

现在我们假设我们有一个PersonViewController,在viewDidLoad里,只需要基于它的model属性设置一些Label即可。

-(void)viewDidLoad{

[superviewDidLoad];

if(self.model.salutation.length>0){

self.nameLabel.text=[NSStringstringWithFormat:

@"%@%@%@",self.model.salutation,self.model.firstName,self.model.lastName];

}else{

self.nameLabel.text=[NSStringstringWithFormat:

@"%@%@",self.model.firstName,self.model.lastName];

}

NSDateFormatter*dateFormatter=[[NSDateFormatteralloc]init];

[dateFormattersetDateFormat:

@"EEEEMMMMd,yyyy"];

self.birthdateLabel.text=[dateFormatterstringFromDate:

model.birthdate];

}

That’sallfairlystraightforward,vanillaMVC.Nowlet’sseehowwecanaugmentthiswithaviewmodel:

这全都直截了当,标准的MVC。

现在来看看我们如何用一个ViewModel来增强它。

@interfacePersonViewModel:

NSObject

-(instancetype)initWithPerson:

(Person*)person;

@property(nonatomic,readonly)Person*person;

@property(nonatomic,readonly)NSString*nameText;

@property(nonatomic,readonly)NSString*birthdateText;

@end

Ourviewmodel’simplementationwouldlooklikethefollowing:

我们的ViewModel的实现大概如下:

@implementationPersonViewModel

-(instancetype)initWithPerson:

(Person*)person{

self=[superinit];

if(!

self)returnnil;

_person=person;

if(person.salutation.length>0){

_nameText=[NSStringstringWithFormat:

@"%@%@%@",self.person.salutation,self.person.firstName,self.person.lastName];

}else{

_nameText=[NSStringstringWithFormat:

@"%@%@",self.person.firstName,self.person.lastName];

}

NSDateFormatter*dateFormatter=[[NSDateFormatteralloc]init];

[dateFormattersetDateFormat:

@"EEEEMMMMd,yyyy"];

_birthdateText=[dateFormatterstringFromDate:

person.birthdate];

returnself;

}

@end

Cool.We’vemovedthepresentationlogicinviewDidLoadintoourviewmodel.OurnewviewDidLoadmethodisnowverylightweight:

Cool!

我们已经将viewDidLoad中的表示逻辑放入我们的ViewModel里了。

此时,我们新的viewDidLoad就会非常轻量:

-(void)viewDidLoad{

[superviewDidLoad];

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

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

}

So,asyoucansee,notalotchangedfromourMVCarchitecture.It’sthesamecode,justmovedaround.It’scompatiblewithMVC,leadstolighterviewcontrollers,andismoretestable.

所以,如你所见,并没有对我们的MVC架构做太多改变。

还是同样的代码,只不过移动了位置。

它与MVC兼容,带来更轻量的ViewControllers。

Testable,eh?

How’sthat?

Well,viewcontrollersarenotoriouslyhardtotestsincetheydosomuch.InMVVM,wetryandmoveasmuchofthatcodeaspossibleintoviewmodels.Testingviewcontrollersbecomesaloteasier,sincethey’renotdoingawholelot,andviewmodelsareveryeasytotest.Let’stakealook:

可测试,嗯?

是怎样?

好吧,ViewController是出了名的难以测试,因为它们做了太多事情。

在MVVM里,我们试着尽可能多的将代码移入ViewModel里。

测试ViewController就变得容易多了,因为它们不再做一大堆事情,并且ViewModel也非常易于测试。

让我们来看看:

SpecBegin(Person)

NSString*salutation=@"Dr.";

NSString*firstName=@"first";

NSString*lastName=@"last";

NSDate*birthdate=[NSDatedateWithTimeIntervalSince1970:

0];

it(@"shouldusethesalutationavailable.",^{

Person*person=[[Personalloc]initWithSalutation:

salutationfirstName:

firstNamelastName:

lastNamebirthdate:

birthdate];

PersonViewModel*viewModel=[[PersonViewModelalloc]initWithPerson:

person];

expect(viewModel.nameText).to.equal(@"Dr.firstlast");

});

it(@"shouldnotuseanunavailablesalutation.",^{

Person*person=[[Personalloc]initWithSalutation:

nilfirstName:

firstNamelastName:

lastNamebirthdate:

birthdate];

PersonViewModel*viewModel=[[PersonViewModelalloc]initWithPerson:

person];

expect(viewModel.nameText).to.equal(@"firstlast");

});

it(@"shouldusethecorrectdateformat.",^{

Person*person=[[Personalloc]initWithSalutation:

nilfirstName:

firstNamelastName:

lastNamebirthdate:

birthdate];

PersonViewModel*viewModel=[[PersonViewModelalloc]initWithPerson:

person];

expect(viewModel.birthdateText).to.equal(@"ThursdayJanuary1,1970");

});

SpecEnd

Ifwehadn’tmovedthislogicintotheviewmodel,we’dhavehadtoinstantiateacompleteviewcontrollerandaccompanyingview,comparingthevaluesinsideourview’slabels.Notonlywouldthathavebeenaninconvenientlevelofindirection,butitalsowouldhaverepresentedaseriouslyfragiletest.Nowwe’refreetomodif

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 职高对口

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1