5

如何在 Viper 架构的项目中创建良好的路由?我开始为路由创建文件,但我不明白接下来我必须做什么。

我创建了一个文件线框优先控制器和线框协议:

//  ChooseLanguageWireframeProtocol.swift

import UIKit

@objc protocol ChooseLanguageWireframeProtocol {
    func presentChooseLanguageViewControllerWindow()
    func presentAuthScreenViewController()
}

在文件线框中我添加:

//  ChooseLanguageWireframe.swift

import UIKit

class ChooseLanguageWireframe: NSObject , ChooseLanguageWireframeProtocol{

    var chooseLanguageScreenViewController: ChooseLanguageViewController?
    var window: UIWindow?

    func presentChooseLanguageViewControllerWindow() {
        let chooseLanguageViewController = UIStoryboard.init(name: "ChooseLanguage", bundle: nil).instantiateViewController(withIdentifier: "ChooseLanguage") as? ChooseLanguageViewController
        self.chooseLanguageScreenViewController = chooseLanguageViewController
        self.window!.rootViewController = chooseLanguageScreenViewController
        self.window!.makeKeyAndVisible()
    }
    func presentAuthScreenViewController() {

    }
}

在我创建 RootWireframe 之后

//  RootWireframe.swift

import UIKit

class RootWireframe: NSObject {

    let chooseLanguageScreenWireframe : ChooseLanguageWireframe?

    override init() {
     //What i must init??
    }

    func application(didFinishLaunchingWithOptions launchOptions: [AnyHashable: Any]?, window: UIWindow) -> Bool  {
        self.chooseLanguageScreenWireframe?.window = window
        return true
    }

}

在文件 AppDelegate 我只改变

var window: UIWindow?
    let rootWireframe = RootWireframe()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        self.rootWireframe.application(didFinishLaunchingWithOptions: launchOptions as [NSObject : AnyObject]?, window: self.window!)
    }

我必须添加或更改什么才能正常工作?

4

2 回答 2

2

一种方法是从 UINavigationController 继承并在其中执行路由逻辑。根据您的任务,您最终可能会在应用程序的不同部分中使用多个类进行路由。

但就像任何流行的流行语一样,您首先必须问自己“解决方案”是否解决了比它创造的问题更多的问题。

当您获得两打屏幕并开始迷失在很久以前通过将情节提要添加到普通旧 xib 中解决的同一问题时,它开始变得有意义。

所以你真的必须退后一步,问问自己你是否真的想遵循这种在这个过程中创建大量类的繁琐架构,这个迷宫几乎不会比标准 MVC 项目更具可读性。

如果您不能使用情节提要并想使用 VIPER,请这样做,如果您可以使用情节提要,请执行 VIPE :-)

但是在大多数项目中,数据模型非常简单,并且呈现方式如此紧密耦合,以至于您对 UIViewController 的去脂化需求为零。

而且我怀疑大多数毒蛇爱好者使用的治疗方法比死亡本身更糟糕。

于 2017-05-26T05:41:28.813 回答
1

2种可能性:

更改 rootViewframe 的 init 以接受您的依赖项并对其进行初始化。顺便说一句,你的变量类型不应该是真正的类型,而是协议,所以你可以在测试中轻松地模拟它

let chooseLanguageScreenWireframe : ChooseLanguageWireframeProtocol?

override init(chooseLanguage: ChooseLanguageWireframeProtocol) {
self.chooseLanguageScreenWireframe = chooseLanguage
}

然后在 appdelegate 中创建您的 chooseLanguageWireframe 实现并将其传递给构造函数。这使得依赖关系清晰可见。您也可以删除可选性,因为您总是对其进行初始化。

或解决方案 2 在 appdelegate 中创建 chooseLanguageWireframe 并将其注入到构造函数之外

lazy var rootWireframe = {
let r = RootWireframe()
r.chooseLanguageScreenWireframe = self.chooseLanguageScreenWireframe
return r
}

在任何情况下,您都需要在某处实例化您的依赖项,它们无法自动创建。您通常使用工厂并借助依赖注入框架(检查 SwiftInject 或 Typhoon)来执行此操作

此外,使用协议类型声明所有依赖项,VIPER 架构的目的是通过参与者之间的隔离来简化测试和模拟

于 2017-07-16T21:27:56.373 回答