工作到現(xiàn)在,對(duì)代碼稍微有點(diǎn)認(rèn)識(shí),,if else 會(huì)寫(xiě)那么點(diǎn)。今天就和大家談?wù)勊斫獾腗VC,,以及現(xiàn)在比較流行的MVVM,。首先我們應(yīng)該明白,計(jì)算機(jī)實(shí)現(xiàn)一個(gè)功能核心代碼就那么點(diǎn),。也許我們經(jīng)常會(huì)聽(tīng)到對(duì)于同一個(gè)問(wèn)題,,菜鳥(niǎo)的實(shí)現(xiàn)的真的就是幾行,可是大牛卻多出了很多文件,。這個(gè)是為什么,?因?yàn)榇笈5摹敖?jīng)驗(yàn)”比較多。,。,。這里面最主要的目的就是為了維護(hù)和可擴(kuò)展。在設(shè)計(jì)模式里面,,如果你能遵循單一原則,,你的代碼就已經(jīng)很好了,。 MVC做iOS開(kāi)發(fā),,一直被教導(dǎo)一定要按MVC模式開(kāi)發(fā)??墒荕VC到底是神馬,?至少在我工作初也不懂是咋回事,!如果網(wǎng)上一搜就是千篇一律的M是數(shù)據(jù)模型,V是視圖,C是控制器,。然后巴拉巴拉的講他們之間是怎么通信的。然并無(wú)卵用,!iOS的MVC展現(xiàn)形式還是有點(diǎn)特殊的,,特別是controller和view緊密在一起,,controller還必須負(fù)責(zé)view的展示,。在服務(wù)器端,view根據(jù)model直接生成HTML,,然后直接扔給瀏覽器去渲染和展示,,通過(guò)Ajax或者js post告訴服務(wù)器controller view的響應(yīng)事件,controller真的做的只是業(yè)務(wù)數(shù)據(jù)的處理,,出來(lái)的結(jié)果其實(shí)還是數(shù)據(jù),,根本沒(méi)有去做UI相關(guān)的事情,。也可以說(shuō)服務(wù)器根本就沒(méi)有view。,。但它有個(gè)瀏覽器,,幫他管理著view和controller之間的交互。而在我們iOS中,,controller可不僅僅只是處理數(shù)據(jù)了,還負(fù)責(zé)view的管理以及事件的傳遞,。 MVC本質(zhì)就是將數(shù)據(jù)展示和數(shù)據(jù)進(jìn)行進(jìn)行隔離,提高代碼的復(fù)用性和擴(kuò)展性,。好吧,我也說(shuō)點(diǎn)并無(wú)什么卵用的,。 看看斯坦福老爺爺?shù)囊粡垐D: 這就是我們所認(rèn)識(shí)的MVC,。我們可以看到,Controller可以和Model通信,,也可以和View進(jìn)行通信,。繼續(xù)看Controller和Model的關(guān)系,,綠色的箭頭代表Controller可以直接進(jìn)行對(duì)Model進(jìn)行訪問(wèn),,也就是說(shuō)Model對(duì)于Controller來(lái)說(shuō)就是透明的,。但是Model并不知道Controller是誰(shuí)。如果Model發(fā)生了變化,,那么就通過(guò)Notification和KVO的方式傳遞給Controller,。同樣的Controller和View之間也是這種關(guān)系,View對(duì)Controller來(lái)說(shuō)就是 透明的,。Controller可以直接根據(jù)Model決定View的展示,。View如果接受響應(yīng)事件則通過(guò)delegate,target-action,,block等方式告訴Controller的狀態(tài)變化,。Controller進(jìn)行業(yè)務(wù)的處理,然后再控制View的展示,。 到這里你會(huì)發(fā)現(xiàn)Model和View并不能直接的進(jìn)行通信,,都必須通過(guò)Controller。那這樣Model和View就是相互獨(dú)立的,。View只負(fù)責(zé)頁(yè)面的展示,,Model只是數(shù)據(jù)的存儲(chǔ),那么也就達(dá)到了解耦和重用的目的,。 說(shuō)這么多不如幾行代碼來(lái)的實(shí)在,。我們以一個(gè)簡(jiǎn)單的例子來(lái)看下: 我們假設(shè)蘋(píng)果根據(jù)買(mǎi)iPhone的人給予不同的優(yōu)惠,學(xué)生優(yōu)惠20%,,it民工優(yōu)惠50%,,其他不優(yōu)惠。 //客戶(hù)類(lèi)
typedef NS_ENUM(NSInteger, CustomerType) {
CustomerTypeStudent,
CustomerTypeiT,
CustomerTypeOther,
};
@interface Customer : NSObject
@property (nonatomic, assign) CustomerType customerType;
@end
//iPhone類(lèi)
@interface iPhone : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *price;
@end
//VC類(lèi)
@interface ViewController ()
@property (nonatomic, strong) iPhone *iphone;
@property (nonatomic, strong) Customer *customer;
@property (weak, nonatomic) IBOutlet UILabel *lblName;
@property (weak, nonatomic) IBOutlet UILabel *lblPrice;
@property (weak, nonatomic) IBOutlet UILabel *lblDiscount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @'手機(jī)優(yōu)惠';
self.lblName.text = self.iphone.name;
self.lblPrice.text = self.iphone.price;
if (self.customer.customerType == CustomerTypeStudent) {
self.lblDiscount.text = @'優(yōu)惠20%';
}
else if (self.customer.customerType == CustomerTypeiT) {
self.lblDiscount.text = @'優(yōu)惠50%';
}
else {
self.lblDiscount.text = @'沒(méi)有優(yōu)惠';
}
}
@end 這個(gè)就是我們最正常的開(kāi)發(fā),,我們的邏輯都是在vc里面寫(xiě)的,。這樣寫(xiě)有木有錯(cuò)呢?一點(diǎn)沒(méi)錯(cuò),,controller本來(lái)就是用來(lái)處理業(yè)務(wù)的,。由于這個(gè)例子比較簡(jiǎn)單,只是做了個(gè)優(yōu)惠判斷,所以我們看不出有啥壞處,。有點(diǎn)開(kāi)發(fā)經(jīng)驗(yàn)的都知道,,如果業(yè)務(wù)復(fù)雜起來(lái),再加上其他亂七八糟的驗(yàn)證,,controller就會(huì)變得很大,,越來(lái)越難以維護(hù)。這個(gè)也是MVC比較明顯的缺點(diǎn),。 MVVM既然controller越來(lái)越臃腫,,越來(lái)越難以維護(hù),我們?cè)趺慈?yōu)化和瘦身呢,?回頭再仔細(xì)看看我們所謂的業(yè)務(wù)邏輯,,是干什么的?無(wú)非就是根據(jù)幾個(gè)數(shù)據(jù)得出一個(gè)數(shù)據(jù)用來(lái)控制view的顯示,。比如展示的是什么文案,,按鈕能不能響應(yīng),頁(yè)面能不能跳轉(zhuǎn)等等,。那MVVM就干了這件事,,幫忙分擔(dān)一下controller里面的部分業(yè)務(wù)邏輯。MVVM更合理的應(yīng)該叫做MV-CM,。 這個(gè)時(shí)候,,controller將不再直接和真實(shí)的model進(jìn)行綁定了,而通過(guò)ViewModel,viewModel進(jìn)行持有真實(shí)的Model,。 我們來(lái)看看剛剛那例子怎么修改: //新建一個(gè)viewModel
//.h文件
@interface viewModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *price;
@property (nonatomic, strong) NSString *discount;
- (id)initWithCustomer:(Customer *)customer iphone:(iPhone *)iphone;
@end
//.m文件
@interface viewModel ()
@property (nonatomic, strong) iPhone *iphone;
@property (nonatomic, strong) Customer *customer;
@end
@implementation viewModel
- (id)initWithCustomer:(Customer *)customer iphone:(iPhone *)iphone
{
if (self = [super init]) {
_customer = customer;
_iphone = iphone;
[self bindData];
}
return self;
}
- (void)bindData
{
self.name = _iphone.name;
self.price = _iphone.price;
if (self.customer.customerType == CustomerTypeStudent) {
self.discount = @'優(yōu)惠20%';
}
else if (self.customer.customerType == CustomerTypeiT) {
self.discount = @'優(yōu)惠50%';
}
else {
self.discount = @'沒(méi)有優(yōu)惠';
}
}
@end
//VC
@interface ViewController ()
@property (nonatomic, strong) viewModel *viewModel;
@property (weak, nonatomic) IBOutlet UILabel *lblName;
@property (weak, nonatomic) IBOutlet UILabel *lblPrice;
@property (weak, nonatomic) IBOutlet UILabel *lblDiscount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = @'手機(jī)優(yōu)惠';
self.lblName.text = self.viewModel.name;
self.lblPrice.text = self.viewModel.price;
self.lblDiscount.text = self.viewModel.discount;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end 看到修改完的代碼,,你會(huì)發(fā)現(xiàn)VC里面已經(jīng)省去了不少的代碼。一切都和viewModel進(jìn)行交流,。這里我只是展示一個(gè)最簡(jiǎn)單的數(shù)據(jù)展示,,如果有其他響應(yīng)事件,是需要viewModel開(kāi)放方法來(lái)進(jìn)行處理的,,并要通知VC處理結(jié)果的,。 關(guān)于MVVM的優(yōu)點(diǎn):
缺點(diǎn):
最后說(shuō)下ReactiveCocoa這個(gè)框架,,這個(gè)雖然和MVVM經(jīng)常一起出現(xiàn),這個(gè)框架主要是幫我們實(shí)現(xiàn)model和view的綁定機(jī)制,。后面會(huì)有文章來(lái)介紹它。 著作權(quán)歸作者所有
|
|
來(lái)自: liang1234_ > 《java進(jìn)階》