[英]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
)。 如果需要調用構造函數,則可以使用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
}
}
在iOS 13中,您可以按以下方式初始化情節提要板視圖控制器:
將初始化程序添加到您的ViewController
類
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")
}
在您的工廠班級:
let viewController = storyboard.instantiateViewController(identifier: "ViewController") { coder in
ViewController(coder: coder, property: <injected property>)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.