6

PS: 这不是一个自以为是的问题。在 VIPER 中连接各种模块是一个合理的疑问。这是一个理论问题,所以没有附加代码。我只需要知道在这种特定情况下我们如何连接 View-Presenter-Router 而不打破基本规则VIPER

我是第一次尝试使用 VIPER。这是我对VIPER的基本理解。

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

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

PS: Presenter 中不会有任何 UIComponents。所以没有import UIKit在presenter中声明。

路由器:负责执行屏幕转换,通常在线框的帮助下完成(可选但在应用程序中有这样的类很好)

Interactor:包含所有业务逻辑。Presenter 将在需要基于业务逻辑进行处理时调用 Interactor。

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

现在问题来了:

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

如果为真,假设我按下了我的一个按钮ViewControllerA并且我需要在其上按下另一个按钮ViewControllerB,显然ViewControllerA会与它交谈PresenterA并告诉它该按钮已被轻按,现在PresenterA应该与它交谈RouterA并告诉它按下ViewControllerB

因为路由器可以访问UIKit我可以轻松地创建一个ViewControllerB使用故事板实例或从 xib 的新实例,但为了推送该实例,我需要 ViewControllerA 的实例。

PresenterA不能持有ViewControllerA对 in 函数的引用或作为参数传递,PresenterA因为UIViewController属于UIKit和 Presenters 不应该有 UI 语句。

我能想到的可能解决方案:

解决方案1:

在创建路由器实例时,将相应ViewController的实例作为其初始化(依赖注入阶段)的一部分传递,这样路由器将始终引用它所属的 ViewController

解决方案2:

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

我想得直吗?我的假设是否正确?如果是,解决此问题的正确方法是什么,请建议

4

1 回答 1

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.
}

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

但这就是我的看法。

于 2018-07-27T09:33:09.710 回答