在两个ViewController之间通信的方式(转帖整理)

一般方法

1)采用代理模式 子viewController设计代理协议,定义协议接口,父viewController 实现协议接口,实现子viewController 退出时将相关数据更新到父视图。 常用程度 ***** 五星

2)采用ios的消息机制 父viewcontroller注册消息,子viewcontroller发送消息,触发父viewcontroller的消息处理。 常用程度 **** 四星

3)采用database做为数据中间的存储媒介,子viewcontroller将状态数据存入DB,父viewcontroller从DB获取数据更新view。 常用程度 * 一星

4)采用ios的NSDefault 存储传递的参数。 常用程度 ** 二星

5)通过AppDelegate 中定义全局变量(或者单例)实现中间数据的存储。 常用程度 *** 三星

 

1.单向交互

第一级level1ViewController负责创建第二级level2ViewController,并且设置level2ViewController相关的属性,然后pushlevel2ViewController。这是最常用的方式。
伪代码

level2ViewController = [[level2ViewController alloc] init];     
[level2ViewController setProp_1];  
[level2ViewController setProp_2];  
[level2ViewController setProp_3];  
[level1ViewController. navigationController pushViewController:level2ViewController];  
[level2ViewController release];

当然还有一种方式是在创建level2ViewController 实例的时候顺便把参数也传了,比较适用于单一参数。如果是多个参数的话,可以用一个Dictionary作为参数的容器。

[[level2ViewController alloc] initWithParam:param]

这种情况下,从level1ViewController的角度来看,它只需要初始化level2ViewController,设置它的一些属性,调用push,然后就什么都不用管了。从level2ViewController的角度来看,当它被push后,在它的生命期内,都不会影响level1ViewController,不需要调用level1ViewController的函数,也没有事件需要通知level1ViewController。

这是最简单的使用情形,也是最理想化的。在项目设计阶段,应该尽量把代码设计成这种结构(仅仅是尽量,并不是必须。而且,也并不是所有的使用场景都都可以设计成这样的结构,毕竟这个太理想化了)。

2.双向交互

level1ViewController和level2ViewController使用共同的一个数据shareData(一定要理解这里“共同”的含义—-两个controller共享同一个数据,并且都有可能进行读写操作,尤其是写操作。如果level2ViewController只对数据进行读操作,那其实就跟前面1中的情形是一致的)。第一级level1ViewController负责创建第二级level2ViewController,并且设置level2ViewController相关的属性,同时还要把shareData传递给level2ViewController,然后pushlevel2ViewController。伪代码如下:

[[level2ViewController alloc] init];  

[level2ViewController setProp_1];  
[level2ViewController setProp_2];  
[level2ViewController setData: shareData];  

[level1ViewController. navigationController pushViewController:level2ViewController];  
[level2ViewController release];

和前一种情形的区别是,在level2ViewController的生命期内,它可能会对shareData进行写操作,当发生这种写操作的时候,需要让level1ViewController知道这种变化,并且作出对应的处理。

这个时候,比较容易想到的一种解决办法是使用Delegate,当level2ViewController写操作shareData时,通过Delegate机制通知level1ViewController,给予level1ViewController一个机会作出正确的响应。(常用方法)

这种办法虽然可行,但并不是首选,在面向对象编程中,经常会提到“解耦”,这里我们就要想办法让这两个controller不要联系的这么紧密。那么怎么办呢?

就是使用MVC模式(UIViewController本身就是MVC中的C)。这个时候,shareData就不应该再是一个普通的数据,而应该封装成model,当model中的数据发生了改变的时候,会发出通知告诉C(和/或V)。这样的话,两个controller之间就比较松散了。引入dataModel后,伪代码如下:

[dataModel alloc] initWithData: shareData];
[[level2ViewController alloc] init];

[level2ViewController setProp_1];
[level2ViewController setProp_2];
[level2ViewController setModel: dataModel];

[level1ViewController. navigationController pushViewController:level2ViewController];
[level2ViewController release];

当level2ViewController修改shareData后,不需要负责通知level1ViewController。shareData会负责通知它的controller。

3. 双向交互,逆向消息传递

这时,基本操作都还是前面描述的1或2中的情形,区别点在于,在level2ViewController的生命期内,发生了某个事件,需要让level1ViewController知道这个事件,并且作出对应的处理。

这个时候,就只能用Delegate了。当level2ViewController发生某个事件时,通过Delegate机制通知level1ViewController,给与level1ViewController一个机会作出正确的响应。

但是!一定要谨慎使用这种方案。如果发现代码中需要用到这种结构,首先应该重新审视项目的架构,看能不能用前面两种方案来处理,可能需要做一定的代码重构。当前面的方案实在是无能为力的时候,才考虑使用此方案。而且,尽量让这种逆向的消息传递更简单,消息事件不要太多。

4.双向交互,大量逆向消息传递

这种情形和前面的3是一样的,但是level2ViewController和level1ViewController之间的消息传递更复杂。

这个时候,同样,要审视代码的结构是否合理。而且很大的可能性是设计不合理,应该考虑把level2ViewController中管理的UIView迁移到level1ViewController中,把controller之间的交互,变成controller内部的view之间的交互,让level1ViewController的内部聚合的更紧密一些,对外部,level1ViewController则表现的更松散。例如,UIAlertView或UIActionSheet,都是UIView的子类。(此处并不绝对,在有些sdk中,类似于UIAlertView或UIActionSheet的组件,它的使用情形,是符合前面3中的描述的,因为这两种组件的行为模式,是有规律性的,可以很方便的复用,举个例子,桌面编程环境中,文件选择器这种组件,通常就是一个顶层window)

最后还要补充说明一些内容。

Cocoa是比较严格的执行了MVC设计模式,其中的UIViewController,可以看成是某种使用场合下,一些内在联系很紧密、并且协同工作的UIView的一个顶层管理容器。

在其他的sdk中,不一定有严格的controller,很有可能只有M和V(C的功能在V内实现),甚至只有V(简单的使用场景,就可以不区分M和C,全在V内管理)。这个时候,就有顶层View的概念(有很多种叫法,比如page、window,或者直接使用abstractWidget),这种逻辑概念上的顶层View,在设计的时候,同样需要考虑它们之间的交互,前面描述的这些情形,同样可以套用。

在用户体验的角度来看,controll或者顶层view,通常被成为“场景”,场景之间是否需要交互,前面的描述,也有一定的参考价值。

但是场景的概念并非总和controll或顶层view严格对应,“场景”是更抽象化的内容,更符合人类的直观感觉,而controller顶层view是更工程化的概念,更精确。在用户体验设计中,有些不同的场景,在逻辑上其实可以属于同一个controller.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值