iOS程序开发中框架的由来的MVC到底是个什么概念

15被浏览2,059分享邀请回答2添加评论分享收藏感谢收起0添加评论分享收藏感谢收起写回答IOS开发中的MVC模式分别对应的是怎样的实体文件_百度知道
IOS开发中的MVC模式分别对应的是怎样的实体文件
我有更好的答案
odel: 一般对应从接口返回的数据解析出来的对象,View :像tableViewCell都是,还有自己定义的一些控件啊Controller,如User
采纳率:71%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。百度搜索MVC模式,一堆,说了一堆很多,反正就是各种好。我这个人表达能力不太强,反正我对这样的模式是认同的,优点也非常多,对代码的重构和维护都是非常好的实现模式。我以前吃过这样的亏,当时还没有不知道什么叫做MVC,当时自己学习做点东西都是各种字典,数组。今天我写一个亲身的例子,从相反的方向来说明下MVC的重要性。
背景:工作需要对界面的一个功能进行升级,原来的红包界面加入了可以叠加使用的红包,不再像以前一样一次只能使用一个,每个红包多了属性:是否可以叠加使用。
大致效果如下:
之前的界面只有展现了红包,点击后就会返回使用,现在增加一个功能,下面两个按钮开始状态分别是:不使用红包,合并红包。
点击合并后出现上面的样子,红色表示选中,灰色表示不选中,服务器端还没有完成,我先做个大概的样子模拟下。
我感觉也不难,无非就是逻辑上考虑点问题但是,事实却不是,原因是公司的代码是下面这样的,一起来看看,我相信我一定会记住的,希望以后都别这样写代码,简直是给别人挖坑。因为该界面还牵扯到其他的功能,有些地方看不懂,时间紧迫不敢重写。顺便说下这个界面代码几乎都没有注释,所有的注释都是我自己添加的。
这是服务器请求的方式和返回数据格式,采用了分页加载。
页数(每页10个)
返回示例:
请求成功且有可用优惠券时:
{&code&:200,&message&:&success&,&content&:
{&coupon_info&:[
&coupon_id&:&323&,
&is_used&:&2&,
&source&:&商城发放&,
&give_time&:&&,
&coupon_price&:&1.5&,
&available_time&:&23小时后可用&
{&coupon_id&:&25003&,
&is_used&:&0&,
&source&:&系统发放&,
&give_time&:& 17:46&,
&expire_time&:& 17:46&,
&coupon_price&:&1.5&
请求成功但没有可用的优惠券时:
{&code&:200,&message&:&success&,&content&:{&coupon_info&:null}}
备注: is_used
0 为未使用, 2为不可用
下面是请求网络数据的函数、
- (void)loadHongBaoJson
if (isNeedIndector) {
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
emptyboxview.hidden = YES;
NSMutableDictionary * mDic = [NSMutableDictionary dictionaryWithCapacity:0];
NSString * userID = USERDEFAULTS_GET(LEXIAO_USER_ID);
userID = userID==nil?@&&:userID;
[mDic setValue:userID forKey:@&user_id&];
[mDic setObject:[NSString stringWithFormat:@&%d&,hongBaoNowPage] forKey:@&page&];
[mDic setValue:@&get_coupon_info& forKey:@&action&];
[AFNetworkTool JSONDataWithUrl:LEXIAO_REQURL_SDQR withDic:mDic success:^(id json) {
NSDictionary * resPonseObject
failureView.hidden = YES;
hongBaoTable.hidden = NO;
NSString * code = [NSString stringWithFormat:@&%@&,[resPonseObject objectForKey:@&code&]];
code=code==nil?@&&:
//成功回调
if ([code isEqualToString:@&200&]) {
emptyboxview.hidden = YES;
[MBProgressHUD hideHUDForView:self.view animated:YES];
NSDictionary * YHQDic = [resPonseObject objectForKey:@&content&];
NSArray * newHongBao = [[NSArray alloc]init];//这里不用初始化吧,下面的那行没有意义吧
newHongBao = YHQDic[@&coupon_info&];
if (newHongBao!=nil&&![newHongBao isEqual:[NSNull null]]){
if ([allHongBao isEqual:[NSNull null]] || allHongBao == nil) {
allHongBao = [[NSMutableArray alloc]init];
[hongBaoTable.footer endRefreshing];
[hongBaoTable.header endRefreshing];
//根据服务器返回数据的个数进行处理
if ([newHongBao count] & 10) {
hongBaoPage = hongBaoNowP
refreshFooter.stateLabel.hidden = NO;
[hongBaoTable.footer noticeNoMoreData];
if ([newHongBao count] == 10) {
hongBaoNowPage ++;
refreshFooter.stateLabel.hidden = NO;
这里进行了函数跳转
[self reloadTableView:YHQDic];
emptyboxview.hidden = NO;
[self setNavBarRightViewWithTitle: nil orImage:nil];
[hongBaoTable.footer endRefreshing];
[hongBaoTable.header endRefreshing];
} fail:^(id error){
[MBProgressHUD hideHUDForView:self.view animated:YES];
[hongBaoTable.footer endRefreshing];
[hongBaoTable.header endRefreshing];
emptyboxview.hidden = NO;
[self setNavBarRightViewWithTitle: nil orImage:nil];
[hongBaoTable setHidden:YES];
hongBaoTable =
[hongBaoTable removeFromSuperview];
[self loadSuDiEmptyBox];
[AFNetworkTool AlertWithTitle:nil andMsg:NSLocalizedString(@&lexiao_wangluolianjieshibai&, nil)];
[self showWithCustomViewWithImage:@&chahao& Message:@&网络连接失败&];
//NSLog(@&失败~~~%@&,error);
if (allHongBao == nil || [allHongBao isEqual:[NSNull null]] || allHongBao.count &= 0) {
[self networkConnectionFailureViewLoad];
failureView.reloadButton.selected = NO;
上面的代码没有什么问题,上面备注“进行了函数跳转地方是这个样子的”,工程中类似这样的if判断,几乎每次在出现网络请求的时候都有,这样判断不下几百个,有的时候也太谨小慎微了,上面已经对YHQDic[@&coupon_info&]已经判断过了,不然也不会执行到这里,这里又进行if判断。还有NSNull类型的指针,目的是为什么呢,OC里面指针所指向的对象类型和指针类型有非常大的联系吗?实在不懂,下面这段代码就是有数据的时候就加载,没有的话就显示一个特殊的视图
- (void)reloadTableView:YHQDic
NSNull *nu = YHQDic[@&coupon_info&];
BOOL isE = [nu isEqual:[NSNull null]];
if ([nu isEqual:[NSNull null]] || [YHQDic[@&coupon_info&] count] &= 0 || YHQDic[@&coupon_info&] == nil) {
[hongBaoTable removeFromSuperview];
hongBaoTable =
emptyboxview.hidden = NO;
[self setNavBarRightViewWithTitle: nil orImage:nil];
[hongBaoTable setHidden:NO];
[emptyboxview setHidden:YES];
[self loadData:YHQDic];//这里又一次跳转
[hongBaoTable reloadData];
当时我要是不看服务器端的文档,我都傻了,取字典里面的数组里面的字典的值,直接取了,一个注释都没有。下面的代码的意思就是,根据服务器返回的字典里面的数组里面的字典,在重新建立一个属于自己的字典。并添加到给tabbleviewcell显示的数组里面。
当时下面要添加到数组里面的字典用的是不可变,我自己kvc赋值还不行,最后改成动态的了,自己为了实现cell点击后状态的切换,
自己在他的那个字典里增加了一个字段isSelected,每次选择单元格要对那个这个key进行赋值。
- (void)loadData:(NSDictionary *)YHQDic
[MBProgressHUD hideHUDForView:self.view animated:YES];
//图片列表
imageList = [[NSArray alloc]initWithObjects:@&1.5+@2x.png&,@&1.1_1.5@2x.png&,@&0.6_1.0@2x.png&,@&0_0.5@2x.png&,@&0_0.0@2x.png&, nil];
NSArray *arr = YHQDic[@&coupon_info&];
//上面刚刚 NSArray *arr = YHQDic[@&coupon_info&]; 下面循环依旧用YHQDic,仅仅就为了计算count
for (NSInteger i = 0; i & arr. i ++) {
//这么多属性也没有考虑建立一个模型,
NSString *is_use = YHQDic[@&coupon_info&][i][@&is_used&];
NSString *couponID = YHQDic[@&coupon_info&][i][@&coupon_id&];
NSString *source = YHQDic[@&coupon_info&][i][@&source&];
NSString *give_time = YHQDic[@&coupon_info&][i][@&give_time&];
NSString *expire_time1 = YHQDic[@&coupon_info&][i][@&expire_time&];
NSString *expire_time = [NSString stringWithFormat:@&过期时间:%@&, expire_time1];
NSString *couponPrice = YHQDic[@&coupon_info&][i][@&coupon_price&];
CGFloat prize = [couponPrice floatValue];
NSString *backI
0 为未使用, 2为不可用
if ([is_use isEqualToString:@&2&]) {
NSString *available_time = YHQDic[@&coupon_info&][i][@&available_time&];
//下面的这四个判断没有必要吧,都一样的结果。
if (prize &= 0.5) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[4];
}else if (prize & 0.5 && prize &= 1.0) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[4];
}else if (prize &= 1.5 && prize & 1) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[4];
}else if (prize & 1.5) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[4];
NSMutableDictionary *dicForHB = [NSMutableDictionary dictionaryWithDictionary:@{@&coupon_id&:couponID,@&source&:source,@&give_time&:give_time,@&expire_time&:available_time,@&coupon_price&:couponPrice,@&backImage&:backImage,@&is_used&:is_use,@&isSelected&:@&NO&}];
[allHongBao addObject:dicForHB];
}else {//可用的红包
if (prize &= 0.5) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[3];
}else if (prize & 0.5 && prize &= 1.0) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[2];
}else if (prize &= 1.5 && prize & 1) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[1];
}else if (prize & 1.5) {
couponPrice = [NSString stringWithFormat:@&%0.1f&,prize];
backImage = imageList[0];
NSMutableDictionary *dicForHB = [NSMutableDictionary dictionaryWithDictionary:@{@&coupon_id&:couponID,@&source&:source,@&give_time&:give_time,@&expire_time&:expire_time,@&coupon_price&:couponPrice,@&backImage&:backImage,@&is_used&:is_use,@&isSelected&:@&NO&}];
[allHongBao addObject:dicForHB];
self.combineArr = [NSMutableArray array];//因为allHongbao内容会变化,所以在变化的时候直接重写查找可以合并的红包
canCombineCnt =0;
for (int i=0; i&allHongBao. i++) {
[self.combineArr addObject:allHongBao[i]];
canCombineCnt ++;
if (canCombineCnt&0) {
self.combineItem.enabled = YES;
self.combineItem.enabled =NO;
[MBProgressHUD hideHUDForView:self.view animated:YES];
下面是点击单元格的方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
if (showMode==0) {
NSString *hbJZ = allHongBao[indexPath.row][@&coupon_price&];
NSString *hongbaoID = allHongBao[indexPath.row][@&coupon_id&];
if (![allHongBao[indexPath.row][@&is_used&] isEqualToString:@&2&]) {
for (UIViewController * tmp in self.navigationController.viewControllers) {
if ([tmp isKindOfClass:[ConfirmExpressViewController class]]) {
ConfirmExpressViewController * vc = (ConfirmExpressViewController *)
//这里进行传值
vc.hongBaoJZ = hbJZ;
vc.hongBaoID = hongbaoID;
[self.navigationController popToViewController:vc animated:YES];
else if(showMode==1)//在合并模式下单元格的点击事件。
HongBaoTableViewCell * cell = (HongBaoTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
NSString *
if ([cell.isSelected isEqualToString:@&YES&]) {
str =@&NO&;
str = @&YES&;
if ([str isEqualToString:@&YES&]) {//被选中了
[self.selectedArr addObject:self.combineArr[indexPath.row]];//添加否则就移除。
[self.selectedArr removeObject:self.combineArr[indexPath.row]];
NSDictionary * dict = self.combineArr[indexPath.row];
[dict setValue:str forKey:@&isSelected&];
[self.combineArr replaceObjectAtIndex:indexPath.row withObject:dict];
NSIndexPath *refreshCell = indexP
[hongBaoTable reloadRowsAtIndexPaths:[NSArray arrayWithObjects:refreshCell, nil] withRowAnimation:UITableViewRowAnimationRight];
[tableView reloadSections:idx withRowAnimation:UITableViewRowAnimationRight];
//要添加保存数据的代码
下面的showMode=0是原来的情况,按字典里面的键取值,给单元格赋值。
红包单元格内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellID = @&cellID&;
HongBaoTableViewCell *myHongBaoCell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (! myHongBaoCell) {
myHongBaoCell = [[HongBaoTableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
if (showMode==0) {//展示所有的
if (allHongBao != nil && ![allHongBao isEqual:[NSNull null]] && [allHongBao count] & 0) {
myHongBaoCell.RMB.text = @&¥&;
myHongBaoCell.hongBaoBackImage.image = [UIImage imageNamed:allHongBao[indexPath.row][@&backImage&]];
myHongBaoCell.hongBaoJZ.text = allHongBao[indexPath.row][@&coupon_price&];
myHongBaoCell.hongBaoLaiYuan.text = allHongBao[indexPath.row][@&source&];
myHongBaoCell.guoQiShiJian.text = allHongBao[indexPath.row][@&expire_time&];
myHongBaoCell.showMode = showM
return myHongBaoC
else if(showMode ==1)//展示可以合并的
if (self.combineArr != nil && ![self.combineArr isEqual:[NSNull null]] && [self.combineArr count] & 0) {
myHongBaoCell.RMB.text = @&¥&;
myHongBaoCell.hongBaoBackImage.image = [UIImage imageNamed:self.combineArr[indexPath.row][@&backImage&]];
myHongBaoCell.hongBaoJZ.text = self.combineArr[indexPath.row][@&coupon_price&];
myHongBaoCell.hongBaoLaiYuan.text = self.combineArr[indexPath.row][@&source&];
myHongBaoCell.guoQiShiJian.text = self.combineArr[indexPath.row][@&expire_time&];
myHongBaoCell.showMode = showM
myHongBaoCell.isSelected = self.combineArr[indexPath.row][@&isSelected&];
return myHongBaoC
#import &UIKit/UIKit.h&
@interface HongBaoTableViewCell : UITableViewCell
@property (strong,nonatomic) UIImageView *hongBaoBackI
@property (strong,nonatomic) UILabel *RMB;
@property (strong,nonatomic) UILabel *hongBaoJZ;
@property (strong,nonatomic) UILabel *hongBaoLaiY
@property (strong,nonatomic) UILabel *guoQiShiJ
描述红包可否合并
@property (nonatomic,strong) UILabel * combineD
展现红包可否合并时候的提示选项,展示的是照片
@property (nonatomic,strong) UIButton *
cell的显示模式,正常模式为0,等待选择模式为1
@property (nonatomic,assign) NSInteger showM
描述在可以合并的状态下是不是被选中
@property (nonatomic,assign)
NSString* isS
上面是单元格头文件的内容,暴漏出这么多的接口,在这个项目中,有些界面暴漏出属性传值达几十个,都是类似于上面那样的赋值方式,代码的复用也几乎就是赋值粘贴。我自己已经按照要求实现功能了,但是费了好大劲才看懂这没有注释的代码,而且这么简单的界面的代码也显的非常长。如此简单的一个界面,如果要增加点新功能的话,可以看出需要做很多无用功,但是如果用MVC模式呢,给红包建立一个模型,类型多的时候只要增加一个属性表示可否拆分,把红包单元格里面类的头文件暴漏出来的这些控件都放在.m文件,只在头文件声明一个红包的模型类属性,在.m文件重写这个属性,然后用模型给cell里面的UI控件赋值。在控制器里面展示红包的数组放的不再是自己定义的字典,而是模型
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
在这个方法声明一个单元格后直接给单元格的模型进行属性赋值不就完了,模型里面如果在加点注释,很快就可以看懂了。
太坑了。以后不知道还会加什么功能,希望这样的活不会落在我身上。
分享这个的目的不是嘲笑,毕竟我也没有工作多长时间,但是感觉基本的编程规范还是要有的,不然你走了,你挖的坑还是让后面的人填补,而且自己的技术也不会提高吧。我感觉这样写代码的目的绝对不是出于时间紧迫吧,用MVC开发绝对比这个要快。自己最讨厌干帮别人埋坑了,你做不好上级怪你能力不行,因为他只看功能。而且他认为目前某些功能已经有了,你接着做都做不好,更是能力低下的表现,比如上面这个简单的例子。而挖坑的人呢,早就跳槽去其他地方了,薪水还涨了。以后如果有时间还要填这些坑,但是我现在不考虑了,目前的打算是只添加注释,能不改就不改,除非一个界面上所有的懂看懂了,并且有时间工作需要的时候再重写,苦逼的我还是继续奋斗吧,为梦想。他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)2783人阅读
iOS常识(48)
iOS里面MVC模式详解
MVC是IOS里面也是很多程序设计里面的一种设计模式,M是model,V是view,C是controller。MVC模式在ios开发里面可谓是用得淋漓尽致。
以下是对斯坦福大学ios开发里面MVC模式的一段话的翻译
主要的宗旨是把所有的对象分为3个阵营,model阵营,view阵营,或者是controller阵营
model(APP的目的)
举个例子,你要做一个打飞机的游戏,那么这个就是太空中这辆飞船的位置,什么机型,每个飞船有多少机枪,护甲有多少等等。这就是model所做的事,而飞机在屏幕上的位置与model没有关系。
model的作用是怎么把model展现在用户面前,它获取了飞船在太空中的位置,然后算出怎么在屏幕上展现出来。
这就是controller,controller控制如何在UI上展现model
view就是controller在仆人,view就是controller所使用的工具。我们尽可能地使view阵营里面的对象通用化。
就像按钮、滑动条等,这些都是苹果自带的。controller利用这些通用的view来做model所需要做的事,view应该是很通用的。因为系统上有好多view,还有和应用相关的功能来控制view。我们要更先进一点,利用通用的view来理解和使用这些功能。
controller向model发消息是100%被允许的,这个箭头是绿色箭头,controller可以问model任何问题,controller知道model的任何事情,因为controller就是用来把model展现在屏幕上,所有它要有完全的访问权,这个箭头是单向的,所以只有controller知道model,这里面的像一个交通标志,从controller到model是白色虚线,所以可以随时跨过去,等一会,我们会看到这个虚线不是一直是虚的。那么controller和view的通信会是怎么样?也是绿色箭头,controller是要吧model显示在屏幕上,所以它可以对view做任何事。例如设个标志,让view做些事情,在屏幕上排列view,数据通信,所以这条路也是白色的虚线,你们看见那个词outlet
outlet是一个表达式用来表示controller的用来和view通信的一个属性,所以我们要在controller里创建outlets到view中去,那model和view怎么样?这门课的宗旨,它们永远不会互相通信。我相信你们都理解为什么model不和view通信,因为model和用户交互界面无关,你可以有一个飞船射击游戏的model,然后通过view来控制,移动飞船到XYZ,射击,你可以这么做,虽然比较笨但你可以这么做。所以model是完全ui独立的,你们都应该明白model不应该和view通信,有些人说,我有一些自定义的view,掌控者model,所以能够显示model。这听起来挺吸引人的,但这不是一个好主意的原因-重用。因为你吧view和model连在了一起,model变了以后view也要重写,view不能被重复利用,model也不能被
其他ui用,比如iPad出来了,因为屏幕大小的原因需要一个新的ui,你就得重写整个view,最好是把这部分放到controller里,建一些更通用的view对象;另一个原因是,如果view和model通信,那么现在所有人都能和model通信了,view和model通信 ,controller和model通信,model就有点hold不住了,如果只有controller和model通信就能很容易搞清楚程序在干嘛,所以把view排除在外,view只是controller的仆人,让controller来通信。所以,在这门课上永远不会发生view和model相互通信的情况,双实线如果你越线我就给你开罚单。view能否允许和controller通信?答案是在某种程度上是可以的,所以这条线是黄色的。view(通用的)和controller(详细控制如何在屏幕展现model)之间的通信是不可见的,view不知道之间在和谁说话,但有一个好的架构。所以在xcode我们可以很好的有组织的连接view和它的controller。所以,view向controller通信的方法,有结构的方法,一个被称为target
action。target action很简单,就是controller自己画了一个target,然后把一个action交个它的view。当view发生了一些事,比如按钮被按滑动条被滑动,它会把action发到target,然后controller就知道按钮被按了。这就是view向controller通信的机制,view回报controller发生了什么。但是view对controller知道的并不多,只是简单的发送target action。事实上,还有view和controller之间比较复杂的通信—比如view和controller要保持同步,所以常常view要告诉controller发生了什么,这是图上的did,或者将要发生什么,这是will,或者要问controller我是否允许什么发生,所以这些will,did,should是view要问的问题。这么做的原因是因为controller把自己设成委托,用协议,希望你们都知道什么是协议,我们会在obj-c里会讲到,设定一个协议,来回应will
did should在一次,view不用知道回应的controller是哪个类 delegation是另一个view和controller通信的方法,另一个很重要的事是,view不是它显示的数据的所有者,这很重要:所以用红色来显示,你们要了解view没有数据,view只是一个平面,用来显示数据,一个显示信息的平台,view没有 实体变量也不会去存储,只有指向他们的指针,所以你iPod库里面 的1000首歌不会是view的实体变量,这种设计使得,比如view不会去管理数据库,跟新iPod歌曲库,这不是view干的活,而是controller或者model干的,如果view不拥有它所显示
的数据,它如何获得数据呢?一个类似delegation的方法,它又一些协议,比如这里的data at和count,这对一个表挺有用的,表可以问表里有多少东西 ,比如5000,那好我要地100到150条的数据,我要用来显示 ,所以view去根据需求来请求数据,这会非常高效的,如果另外一头知道怎么管理一个巨大的数据库,而只是提取其中需要的几条,因为ipod里有10000首歌,但屏幕上只显示7首。你要这种功能,但不要把它写在一个view里,view是通用的用来显示的,controller金额model一起来有效率的提供信息,类似地,view会有一个数据源的设置,controller会回应数据源,注意,数据源的delegation永远是controller,或者是controller的指定的第三方,但不可能是model,controller的工作是把model的信息传递给view,响应所有的delegation。因为它能获取model里的数据,决定怎么在屏幕上显示,这是它的职能,所以它要参与这个循环,你们可能需要这些data
at和count的方法,可能只是一行代码,问model数据是什么,然后model把数据给你,即使这是一行代码,也需要controller来参与,因为这是controller的工作,获取model显示在屏幕上,我反复讲了5编,这是controller的工作,在iOS开发这很重要,你要给他机会做他的工作,永远不要越过view和model中间的线,还有一件事,model能向controller发话吗这个很明显,肯定不行的。model是ui独立的,不能向controller发话,这是controller的工作来用view显示model,那么当model的一些东西改变了,你要更新controller的时候该怎么办呢?你有个数据库,某人在数据库里写了些东西,比如你的飞船游戏里的其他玩家攻击了你
的飞船,现在model改变了是因为飞船受伤了 。
在iOS里面我们实现的方法是用一个广播站就像信息广播机制,有2个机制,通知关键数据监听,当model改变了,它就在广播站里广播,controller收听到了,然后去model什么东西改了。这是完全不可见的,同步的,这里的kvo也可以用于view和controller但不会是view和model,view不会有面向model的广播,view和controller会互相有广播。model广播非常好用,因为是不可见的,但也有限制,只能通知被允许通信的对象发生了什么事,现在我们有了各个阵营间所有的通信机制,我们要建立一个复杂应用。复杂应用不仅仅只有一个controller。view可能有100个controller至少有十几个控制很多的view,比如登录界面,点击了什么出个表,再点一下出来个其他的什么,各种各种的view被controller管理着,那要怎么做复杂应用呢?答案是把mvc组合
成mvc群,图上你们可以看到某些controller的view是另一个mvc,比如中间这个,它有3个mvc view,所以这很普遍,你在一个view里按下了个按钮,而另一个mvc显示了数据,这个图有个好的地方是,所有的箭头只通过规定的界限。你看其中任何一个部分,你明白这部分是干嘛的,一个model只有一个controller

我要回帖

更多关于 java程序开发学习中心 的文章

 

随机推荐