如何使用依赖注入和工厂模式实现 ViewController 自定义初始化?
How to Implement ViewController custom init using dependency injection and factory patterns?
我正在尝试使用 DI 和工厂实现简单示例。
ViewController.swift
class VIewController : UIViewController {
private let factory: ViewControllerFactory
init(with factory: Factory) {
self.factory = factory
super.init(nibName: nil, bundle: nil)
}
}
protocol ViewControllerFactory {
func makeViewController() -> ViewController
}
class DependencyContainer {
///
}
extension DependencyContainer: ViewControllerFactory {
func makeViewController() -> ViewController {
return ViewController(with: self)
}
}
AppDelegate.swift
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let container = DependencyContainer()
let rootViewController = container.makeViewController()
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
return true
}
我在故事板中设计了视图控制器。我如何才能成功将我的代码更正为 运行 应用程序?
应用崩溃:
- 我正在从视图控制器中删除情节提要入口点,但是出口为零,并且在我使用它们时崩溃了。
- initWithCoder 正在调用,以防我不从情节提要中删除该入口点。
您所描述的行为是故事板的工作方式(即它们称为 initWithCoder
)。如果您需要调用您的构造函数,您可以使用一个 nib 文件,然后调用您的构造函数,该构造函数调用 init(nibName:bundle:)
并将正确加载 nib 文件。这适用于当前 iOS 版本。
通过故事板获取构造函数注入的唯一方法是使用 iOS 13 并使用新的 @IBSegueAction
,这将为您提供一个编码器,您可以将其传递给构造函数然后调用 super initWithCoder
.
有不同类型的依赖注入。您目前正在尝试使用基于构造函数的依赖注入,不幸的是,它实际上不适用于情节提要,因为它们需要使用解码器进行初始化。 iOS 13 确实引入了一些使这种方法成为可能的附加功能,但目前,您可以改用基于 setter 的依赖项注入。
类似于以下内容:
class ViewController: UIViewController {
var factory: ViewControllerFactory!
}
protocol ViewControllerFactory {
func makeViewController() -> ViewController
}
class DependencyContainer {
let storyboard: UIStoryboard = UIStoryboard(name: "Storyboard", bundle: Bundle.main)
}
extension DependencyContainer: ViewControllerFactory {
func makeViewController() -> ViewController {
guard let vc = storyboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController else {
fatalError("Unrecognised viewController")
}
vc.factory = self
return vc
}
}
在iOS13中,你可以初始化一个故事板视图控制器如下:
为您的 ViewController
class
添加初始化程序
let property: Property // Your injected property
required init?(coder: NSCoder, property: Property) {
self. property = property
super.init(coder: coder)
}
required init?(coder: NSCoder) { // You'll need to add this
fatalError("init(coder:) has not been implemented")
}
在你的工厂class:
let viewController = storyboard.instantiateViewController(identifier: "ViewController") { coder in
ViewController(coder: coder, property: <injected property>)
}
我正在尝试使用 DI 和工厂实现简单示例。
ViewController.swift
class VIewController : UIViewController {
private let factory: ViewControllerFactory
init(with factory: Factory) {
self.factory = factory
super.init(nibName: nil, bundle: nil)
}
}
protocol ViewControllerFactory {
func makeViewController() -> ViewController
}
class DependencyContainer {
///
}
extension DependencyContainer: ViewControllerFactory {
func makeViewController() -> ViewController {
return ViewController(with: self)
}
}
AppDelegate.swift
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let container = DependencyContainer()
let rootViewController = container.makeViewController()
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
return true
}
我在故事板中设计了视图控制器。我如何才能成功将我的代码更正为 运行 应用程序?
应用崩溃:
- 我正在从视图控制器中删除情节提要入口点,但是出口为零,并且在我使用它们时崩溃了。
- initWithCoder 正在调用,以防我不从情节提要中删除该入口点。
您所描述的行为是故事板的工作方式(即它们称为 initWithCoder
)。如果您需要调用您的构造函数,您可以使用一个 nib 文件,然后调用您的构造函数,该构造函数调用 init(nibName:bundle:)
并将正确加载 nib 文件。这适用于当前 iOS 版本。
通过故事板获取构造函数注入的唯一方法是使用 iOS 13 并使用新的 @IBSegueAction
,这将为您提供一个编码器,您可以将其传递给构造函数然后调用 super initWithCoder
.
有不同类型的依赖注入。您目前正在尝试使用基于构造函数的依赖注入,不幸的是,它实际上不适用于情节提要,因为它们需要使用解码器进行初始化。 iOS 13 确实引入了一些使这种方法成为可能的附加功能,但目前,您可以改用基于 setter 的依赖项注入。
类似于以下内容:
class ViewController: UIViewController {
var factory: ViewControllerFactory!
}
protocol ViewControllerFactory {
func makeViewController() -> ViewController
}
class DependencyContainer {
let storyboard: UIStoryboard = UIStoryboard(name: "Storyboard", bundle: Bundle.main)
}
extension DependencyContainer: ViewControllerFactory {
func makeViewController() -> ViewController {
guard let vc = storyboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController else {
fatalError("Unrecognised viewController")
}
vc.factory = self
return vc
}
}
在iOS13中,你可以初始化一个故事板视图控制器如下:
为您的 ViewController
class
let property: Property // Your injected property
required init?(coder: NSCoder, property: Property) {
self. property = property
super.init(coder: coder)
}
required init?(coder: NSCoder) { // You'll need to add this
fatalError("init(coder:) has not been implemented")
}
在你的工厂class:
let viewController = storyboard.instantiateViewController(identifier: "ViewController") { coder in
ViewController(coder: coder, property: <injected property>)
}