簡體   English   中英

如何使用依賴項注入和工廠模式實現ViewController自定義init?

[英]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
    }
}

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM