【问题标题】:Dependency injection with storyboards使用故事板进行依赖注入
【发布时间】:2021-03-23 19:16:30
【问题描述】:

我正在尝试使用以下代码将依赖项传递到从情节提要实例化的视图控制器中

init?(coder: NSCoder, alertPresenter: AlertPresenterProtocol = , viewModel: EmployeesViewModel) {
        self.alertPresenter = alertPresenter
        self.employeeViewModel = viewModel
        super.init(coder: coder)
    }
required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

但是我收到了 fatalError 消息。从情节提要实例化时,如何通过初始化程序将依赖项传递给视图控制器

【问题讨论】:

  • “但我收到了致命错误消息。”因为那是你说要做的。
  • 也请出示真实代码。
  • 问题是当从故事板实例化时,如何通过初始化程序将依赖项传递给视图控制器
  • 这就是prepareForSegue 的用途。
  • 我没有使用它在视图控制器之间传递变量。我正在尝试使视图控制器可测试

标签: swift initialization storyboard protocols


【解决方案1】:

您的故事板必须使用标有@IBSegueAction 的方法,该方法将接受最小编码器参数并返回与目的地相对应的对象。在该方法中,您应该使用自定义 init 方法初始化目标视图控制器。

【讨论】:

  • 这是唯一正确的答案。 :) Segue 操作尚未被一般编程人员接受。人们似乎没有注意到它们的存在。但他们很棒!它们允许您将自己的代码与 segue 目的地的故事板实例化结合起来。
  • @matt 也许你可以帮我看看这个功能是否有一些限制stackoverflow.com/questions/69285494/…
【解决方案2】:

简短的回答是,你不能。

您使用UIStoryboardinstantiateViewController(withIdentifier:) 方法从情节提要中实例化一个视图控制器。根据文档:

每次调用此方法时,它都会使用 init(coder:) 方法创建视图控制器的新实例。

该方法为你创建视图控制器,它不提供任何方式让你注入依赖。

当视图控制器由 segue 创建时,prepareForSegue 方法为您提供了一个 UIStoryboardSegue 对象,该对象引用了已经初始化的 destination 视图控制器。也无法通过这里的初始化程序注入依赖项。

一些纯粹主义者会把这个事实当成你不应该使用故事板的理由。

就我个人而言,我从未发现这是一个令人信服的论点。我只是在实例化之后将依赖项分配为视图控制器的属性。这也适用于单元测试。这确实意味着您的依赖项必须声明为可选项,这会使您的代码不那么优雅。同样,我不认为这是放弃情节提要的许多便利的令人信服的理由。

【讨论】:

  • 实际上,这不是你不应该使用故事板的原因。部分原因是它们不能很好地与 Git 协作,部分原因是您无法将故事板 segues 与路由器/协调器/演示者架构相结合。
【解决方案3】:

如果可以从初始化程序 init?(coder:) 中派生依赖项,则执行此操作并将其设置在那里。

如果不是,则不能在那里设置。

无论如何,既然您说涉及单元测试,您需要将依赖项设为外部可设置属性,并从单元测试中设置它。

【讨论】:

    猜你喜欢
    • 2016-10-27
    • 2015-09-26
    • 2014-01-19
    • 2014-03-25
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多