iOS VIPER架构,谁必须实例化整个模块?
考虑到VIPER结构
我有两个模块A和B.第一个模块A,通过演示者,想要执行一个必须在模块B中完成的动作,所以告诉它的线框去做。 问题是,谁负责实例化整个模块(视图,交互者,演示者…)。 我看到了一些不同方法的例子:
- 在应用程序的开始创build所有模块。
- 在模块的线框中创build整个模块,所以在这种情况下,BWireframe的一个类方法即时处理所有的B模块。
考虑到线框负责路由,是否也负责创build其模块?
TL; DR :我build议你应该使用像Typhoon这样的DI框架,并让它处理实例化。
您可能不希望线框实例化VIPER模块(View,Presenter,Interactor,DataManager)中的所有内容的原因是,您将直接为这些组件创build依赖关系。
依赖性使得软件不能改变:如果我们用洋葱结构 / 六边形结构的帽子来思考它,那么线框就会通过不仅知道视图而且还知道数据pipe理器,跨越至less两个独立的洋葱层的边界。
这迫使我们将线框视为通用的基础结构类:即应用程序最外层的东西。
然而,这与线框的其他(更真实的)责任相矛盾:做导航。 虽然这仍然是基础设施层,但它在UIKit
( -presentViewController:
等等)中是-presentViewController:
。
所以恕我直言,VIPER的线框做得太多了。
唯一明智的做法是把这两项责任分开:
- VIPER类的初始化:可以引入一个工厂 ,或者使用专门解决这个问题的DI工具
- 做导航:这保持在一个
Wireframe
的职权范围内。
补充笔记
如果你想知道“ 谁来实例化下一个模块吗?”,那么恕我直言,我认为某些Module A
的线框与Module B
的线框对话是不正确的,尽pipeVIPER的post说了什么。
原因在于Module A
现在将依赖于Module B
,导致紧密的耦合:这就损害了模块的目的。 在GitHub的VIPER-TODO项目上有关此主题的更多讨论=]
希望这可以帮助。
我认为模块的进入门是线框,所以我同意你的第二种方法。
创build一个模块包括创build它的所有对象,在我看来这是一种浪费。
-
使用这个Xcode插件( https://github.com/natangr/ViperTemplate )自动创build并启动VIPER文件。
-
阅读这篇文章,了解关于VIPER实例化的更多高级技巧(以及上述插件的解释): https : //www.ckl.io/blog/best-practices-viper-architecture/
在自己的路由器上有模块初始化代码将消除一堆代码重复,特别是对于大型项目。 您需要创build一次这些扩展名:
// ReusableView.swift protocol ReusableView: class {} extension ReusableView { static var reuseIdentifier: String { return String(describing: self) } } // UIViewController.swift extension UIViewController: ReusableView { } // UIStoryboard.swift extension UIStoryboard { func instantiateViewController() -> T where T: ReusableView { return instantiateViewController(withIdentifier: T.reuseIdentifier) as! T } }