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

时间:2018-07-27 08:43:36

标签: ios swift viper

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

的基本规则

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

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

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

PS:演示者中将没有任何UIComponent。因此,主持人中没有import UIKit声明。

路由器:负责执行屏幕转换,通常是借助线框完成的(可选,但可以在应用中使用此类)

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

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

现在是一个问题:

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

如果为true,则假设我按下ViewControllerA上的一个按钮,并且需要在其上方按下另一个ViewControllerB,显然ViewControllerA会与PresenterA通话并告诉轻按一下按钮,现在PresenterA就应该与RouterA对话,并告诉其按下ViewControllerB

因为路由器可以访问UIKit,所以我可以使用情节提要实例或通过xib轻松创建ViewControllerB的新实例,但是为了推送该实例,我需要ViewControllerA的实例。

但是PresenterA不能保存对ViewControllerA的引用,也不能在函数中作为PresenterA的参数传递,因为UIViewController属于UIKit并且Presenters是不应该包含UI语句。

我能想到的

可能的解决方案:

解决方案1:

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

解决方案2:

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

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

1 个答案:

答案 0 :(得分:4)

关于VIPER for iOS应用程序的任何建议或意见值得商,,因为VIPER并不完全适合iOS的UIKit设计。但是如果我要讨论我的两分钱:

首先,我认为UIViewController非常适合Presenter在VIPER模式中的角色,因此ViewControllerA不需要与自身和{之间的任何类进行对话{1}}-只需直接与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.
}

Router应该跟踪导航堆栈并保持对当前显示的ViewController

的引用

但这就是我的看法。