UIViewController解耦尝试

当我们使用UIViewController时,从一个ViewController跳到另外一个ViewController,最简单的代码(不用storyboard的情况下)就是alloc一个实例,然后用navigation controller去push它。比如

而这样一来,这个ViewController必须知道另外一个ViewController的存在,而且需要import它的头文件。这样一来,两个ViewController就紧密耦合了。

在一般的程序里面,这么做没有任何问题。但是我们公司的两个主打产品有一个特殊需求就是:两个产品共用部分界面,而这些共用界面中的一些按钮,点击之后,在不同的程序里需要push出不同的界面(界面初始化需要的参数是一样的,但就是完全不同的界面)。而这两个产品又是由不同的小组去完成的,他们不共享同一个工程。

这时,我们想到的是将这些共用界面提取出来做成framework。那么问题就出现了:我如果在framework里面的view controller新建一个下一级view controller,就需要知道下一级view controller的头文件,下一级view controller又实际存在于每一个主工程里面。这样就出现了循环依赖的情况,这样做出来的framework即使能编译通过也没法维护。

好在ObjC是一个动态语言,实际上我们根本不需要知道一个类的信息就能初始化它。使用的方法就是NSClassFromString()函数,此时你只要知道class名字就行,如果它返回一个Class不为nil,就可以实例化它,并且用KVC注入需要的property。所以稍加改进的代码如下:

虽然这个能解耦,但是每次写那么冗余的代码总归不易维护。所以我尝试把这些东西抽象出来,以配置文件的形式,在不同工程里配置不同的界面。灵感来自于前几年在写Java的时候用的Spring。最后做了一个叫做EMViewControllerManager的东西。

EMControllerManager的配置文件的基本结构如下:

其中Test1Test2被称为view controller名称(昵称)。ClassName指定了view controller的真实类名,而Dependencies可以做一点基础的DI功能。

然后在AppDelegate里面载入配置文件:

而在view controller里面,可以这么来初始化一个view controller对象:

其中Named:是view controller的昵称,withPropertyValues:是初始化之后马上注入的property。

不同的工程只要改配置文件,而不需要改具体的代码,就能达到差异化的效果。

具体用法请阅读EMControllerManager的Github主页

No Comments

Post a Comment