如何在VIPER设计模式中将ViewController参考传递给路由器?

San*_*ari 5 viper ios swift

PS: 这不是一个自以为是的问题。在VIPER中连接各种模块是一个合理的疑问。这是一个理论问题,因此没有附加任何代码。我只需要知道在这种特定情况下如何连接View-Presenter-Router,而不会违反VIPER

我是第一次尝试与VIPER接触。这是我对VIPER的基本了解。

视图:应该显示UI控件并捕获IBActions并调用其演示者的委托方法来处理事件

演示者:将处理所有与UI相关的数据,并准备进行渲染的数据并将其移交给View。每当需要屏幕转换时,它将调用其路由器并要求路由器执行转换

PS: Presenter中将没有任何UIComponent。因此import UIKit,主持人中没有任何发言。

路由器:负责执行屏幕转换,通常在线框的帮助下进行(可选,但最好在应用中使用此类)

Interactor:包含所有业务逻辑。只要需要基于业务逻辑进行处理,Presenter就会调用Interactor。

实体: POJO类(简单的Swift对象或Core数据实体)。

现在出现问题:

如果我的假设是正确的,那么Presenter应该是没有UIKit访问权限的普通Swift类。

如果为true,则假设我按了自己的按钮,ViewControllerA并且需要ViewControllerB在其顶部按另一个按钮,显然ViewControllerA会与之交谈PresenterA并告知该按钮已被轻按,现在PresenterA应该RouterA与之交谈并告诉其按入ViewControllerB

因为Router可以访问,UIKit所以我可以ViewControllerB使用Storyboard实例或通过xib 轻松创建一个新实例,但是为了推送该实例,我需要ViewControllerA的实例。

但是PresenterA不能包含对函数的引用ViewControllerA或将其作为参数传递给PresenterAin函数,因为UIViewController属于UIKit和Presenters不应具有UI语句。

我可能想到的解决方案:

解决方案1:

在创建Router实例时,将相应的ViewController实例作为其init(依赖注入阶段)的一部分传递,以这种方式,Router将始终引用其所属的ViewController

解决方案2:

让Router声明其协议并在ViewController中实现它,并且每当需要引用ViewController时,都使用Router的委托。但这与VIPER的规则矛盾,即路由器不应与View对话。

我在想什么吗 我的假设对吗?如果是,解决此问题的正确方法是什么,请提出建议

mag*_*zbc 5

任何关于 VIPER for iOS 应用程序的建议或意见都值得商榷,因为 VIPER 并不严格符合 iOS 的 UIKit 设计。但是,如果我可以讨论一下我的两分钱:

首先,我认为这UIViewController完全符合PresenterVIPER 模式中的角色,因此ViewControllerA不需要与自身之间的任何类进行对话,并且Router- 只需Router直接与之通信即可。

其次,应该只有一个Router对象——因为应用程序只有一个视图/导航堆栈。出于这个原因,为 实现Singleton模式是理想的Router,因此ViewControllerA(或者Presenter,如果您希望您在该模式中ViewControllers扮演 的角色View)不需要保留对 的引用Router

第三,您不需要将引用传递ViewControllerA给您的Router-Router应该已经拥有对它的引用,因为Router应该首先呈现它。类似的东西:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
{
    // ...

    window?.rootViewController = Router.shared.rootViewController

    // ...
}

class Router
{
    static let shared = Router()

    let rootViewController = ViewControllerA() // or UINavigationController, or UITabBarController etc.
}
Run Code Online (Sandbox Code Playgroud)

Router 应该跟踪导航堆栈并保持对当前呈现的引用 ViewController

但这就是我的看法。