iOS設(shè)計(jì)模式之MVC淺談

前言

博主剛開始做iOS的時(shí)候雖然知道有一些設(shè)計(jì)代碼的模式,如MVC,MVVM等,但是那時(shí)候完全沒考慮這些,寫代碼不經(jīng)過大腦,為了實(shí)現(xiàn)一個(gè)功能代碼直接就往viewController里面放,現(xiàn)在比較閑才考慮要重構(gòu)一下代碼。本文主要介紹MVC,希望初學(xué)者一開始就養(yǎng)成好習(xí)慣。

iOS的設(shè)計(jì)模式十分重要,他決定了你的代碼的耦合性和重用性,我們的目的就是要解耦合,盡量使代碼模塊化,提供復(fù)用率和移植性。接下來我就簡單的說說MVC模式。

什么是MVC

MVC是model-view-control的簡稱。

View——顧名思義,就是存放視圖使用的。

Model——即模型。模型一般都有很好的可復(fù)用性,統(tǒng)一管理一些數(shù)據(jù)。

Controller——控制器,充當(dāng)一個(gè)CPU的功能,即該應(yīng)用程序所有的工作都由Controller統(tǒng)一調(diào)控。

MVC模式能夠完成各司其職的任務(wù)模式,由于降低了各個(gè)環(huán)節(jié)的耦合性,大大優(yōu)化Controller的代碼量,當(dāng)程序調(diào)試時(shí),如果某一個(gè)功能沒有按照既定的模式工作,可以很方便的定位到到底是Controller還是View還是Model出了問題,而且還利于程序的可復(fù)用性,建議在程序中能多多使用這個(gè)模式。

MVC原理

官方的圖,形象生動(dòng):

1.? 圖中,綠色的箭頭表示直接引用。 對(duì)View 的直接引用體現(xiàn)在 IBOutlet 上。 當(dāng)引用一個(gè)View 時(shí),比如Button。 需要在ViewController


中聲明一個(gè)? IBOutlet? UIButton * btn;

2. 然后,我們看View 是怎么向 Controller 通信的。對(duì)于這個(gè), ?iOS 有三種常見的模式:

設(shè)置View對(duì)應(yīng)的Action Target。如設(shè)置UIButton的Touch up inside的Action Target。

設(shè)置View的Delegate,如UIAlertViewDelegate, UIActionSheetDelegate,UITextFieldDelegate等。

設(shè)置View的data source, 如UITableViewDataSource。

通過以上三種模式,View既能向Controller通信,又無需知道具體的Controller是誰,這樣,View 就與Controller解耦了。

(博主將會(huì)在以后的博文中詳解Delegate、Protocol)

實(shí)戰(zhàn)

1、不使用MVC的情況大概說一下,就是所有代碼都在viewController里面,具體什么樣子估計(jì)自己明白,我就不啰嗦了。

2、如何使用MVC:

項(xiàng)目結(jié)構(gòu):

BtnView里面只存放界面顯示的控件,btnModel里面進(jìn)行數(shù)據(jù)處理并且暴露API。ViewController里面只調(diào)用API。

BtnView.h代碼:

@property (nonatomic, strong) UIButton *saveBtn;? //點(diǎn)擊該按鈕,保存數(shù)據(jù)

@property (nonatomic, strong) UIButton *loadBtn;? //點(diǎn)擊該按鈕,加載數(shù)據(jù)

- (void)viewInit;? //添加一個(gè)方法,用于初始化控件,暴露API供C調(diào)用初始化view

BtnView.m代碼:

- (void)viewInit {

_saveBtn = [UIButton buttonWithType:UIButtonTypeCustom];

[_saveBtn setFrame:CGRectMake(50, 50, 150, 80)];

[_saveBtn setTitle:@"保存" forState:UIControlStateNormal];

[_saveBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];? //默認(rèn)的頁面背景色是白色,butotn上的文字的默認(rèn)顏色也是白色,所以在此處將button上的文字顏色設(shè)置為黑色,以便顯示

[self addSubview:_saveBtn];

_loadBtn = [UIButton buttonWithType:UIButtonTypeCustom];

[_loadBtn setFrame:CGRectMake(50, 160, 150, 80)];

[_loadBtn setTitle:@"加載" forState:UIControlStateNormal];

[_loadBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

[self addSubview:_loadBtn];

}

btnModel.h代碼

@interface btnModel : NSObject

-?(void)save;//暴露的API,供C調(diào)用

- (void)load;//暴露的API,供C調(diào)用

@end

btnModel.m代碼

@implementation btnModel

-?(void)save{

NSLog(@"保存。。。");

}

-?(void)load{

NSLog(@"加載。。。");

}

@end

那么我么就會(huì)有一個(gè)思路——在Controller中,當(dāng)我們?yōu)榘粹o添加了target-action模式之后,對(duì)應(yīng)要實(shí)現(xiàn)的action方法里面,是不是只需要調(diào)用MModel.h里面的對(duì)應(yīng)的-(void)save和- (void)load方法就行了呢?完全正確!看,這就是C通過API調(diào)用M!

V和M都已經(jīng)分配好了,接下來就是看C如何協(xié)調(diào)分配了。ViewController.h中的代碼如下:

#import "btnModel.h"

#import "BtnView.h"

@interface ViewController : UIViewController

@property (nonatomic, strong)? BtnView*aView;? //實(shí)例化一個(gè)VView的對(duì)象

@property (nonatomic, strong) btnModel *mModel;? //實(shí)例化一個(gè)MModel的對(duì)象,以便于調(diào)用MModel中的方法

@end

ViewContro.m中的代碼如下:

#import "ViewController.h"

#define deviceScreenWidth [[UIScreen mainScreen]bounds].size.width

#define deviceScreenHeight [[UIScreen mainScreen]bounds].size.height

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

_aView = [[BtnView alloc]initWithFrame:CGRectMake(0, 0, deviceScreenWidth, deviceScreenHeight)];? //初始化時(shí)一定要設(shè)置frame,否則VView上的兩個(gè)按鈕將無法被點(diǎn)擊

[_aView viewInit];

[_aView.saveBtn addTarget:self action:@selector(saveBtnPressed:) forControlEvents:UIControlEventTouchUpInside];? //為“保存”按鈕添加target-action模式

[_aView.loadBtn addTarget:self action:@selector(loadBtnPressed:) forControlEvents:UIControlEventTouchUpInside];? //為“加載”按鈕添加target-action模式

[self.view addSubview:_aView];

_mModel = [[btnModel alloc]init];

}

- (void)saveBtnPressed : (UIButton*)sender{

[_mModel save];? //調(diào)用MModel.h中的方法(API)

}

- (void)loadBtnPressed : (UIButton*)sender{

[_mModel load];? //調(diào)用MModel.h中的方法(API)

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

運(yùn)行效果,點(diǎn)擊保存和加載后臺(tái)打印相應(yīng)的日志:

代碼里面有一些注意事項(xiàng),我都用注釋的形式寫在了代碼的后面,請(qǐng)讀者自行研究判斷,此處不再贅述,有疑問歡迎留言討論。從C的代碼中可以看到,如何在MVC中使用target-action模式(delegate模式和datasource模式,暫時(shí)不在這個(gè)案例中講述),如何在C中調(diào)用M中的API。雖然M+V+C里面的代碼總量比不使用MVC模式多了一些,但MVC模式寫出來的代碼層次分明,結(jié)構(gòu)清楚,分工明確,為以后修改代碼、調(diào)試程序都帶來了極大的便利。比如你要修改顯示的效果,只需要修改V中的就行,然后按照調(diào)理在C中添加相應(yīng)的方法,多么明確。

總結(jié)

使用設(shè)計(jì)模式來寫代碼真的可以減少很多沒必要的重復(fù)累贅的代碼,提高代碼的可讀性和可移植性,降低耦合度,大大提高開發(fā)的效率,博主親身經(jīng)歷,維護(hù)沒有模式的代碼會(huì)讓你有砸鍵盤的沖動(dòng),希望本文能對(duì)廣大初學(xué)者有所幫助。博主會(huì)在之后的日子更新一篇MVVM模式的文章,敬請(qǐng)期待····

本文參考優(yōu)秀博文:

http://leopard168.blog.163.com/blog/static/168471844201111214163883/

http://www.mamicode.com/info-detail-1114664.html


博主的微博、CocoaChina博客、CSDN博客同步更新,歡迎關(guān)注:

新浪微博:http://weibo.com/p/1005052308506177/home?from=page_100505_profile&wvr=6&mod=data&is_all=1#place

CocoaChina:http://blog.cocoachina.com/477998

CSDN:http://blog.csdn.net/czkyes

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容