MVC、Swift 中的依赖注入

问题描述 投票:0回答:2

我正在构建一个遵循 SOLID 原则和 MVC 架构的简单应用程序。我想在我的 NetworkClass 中解析来自服务器的图像,并将它们显示在我的 ViewController 的 CollectionView 中。这是我的视图控制器:

protocol NetworkServiceProtocol {
    func parseImages() -> [Image]
}

class ViewController: UIViewController {
    
    @IBOutlet weak var imageCollection: UICollectionView!

    private let networkService: NetworkServiceProtocol
   
    convenience init(service: NetworkServiceProtocol) {
        self.init()
        self.networkService = service
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        images = networkService!.parseImages()
    }

}

这是我的 NetworkService 类(稍后我将进行解析):

class NetworkService: NetworkServiceProtocol {
    
    func parseImages() -> [Image] {
        return [Image]()
    }
    
}

问题是,当我运行此代码时,它在调用

viewDidLoad()
时在
networkService!
中崩溃。我发现问题出在实例化 NetworkServiceProtocol 上。我应该在哪里以及如何实例化它?如有任何帮助,我们将不胜感激!

ios swift model-view-controller dependency-injection solid-principles
2个回答
0
投票

发生这种情况是因为您正在从情节提要初始化您的

ViewController
,而故事板正在使用您的
required init?(coder: NSCoder)
,它会抛出
fatalError

要解决这个问题,首先要改变:

    required init?(coder: NSCoder) {
            //error: networkService not initialized
            super.init(coder: coder)
        }

现在出现此错误是因为

networkService
类属性未通过此初始化程序初始化。现在为了解决这个问题,您可以在类中给它一个默认属性,例如
let networkService = NetworkServiceProtocol()
,并在通过故事板初始化后立即将其设置为您想要的
NetworkServiceProtocol
对象。 (另一种选择是使其成为可选)

注意:您必须删除私有访问修饰符才能从另一个类中设置它。如果你仍然希望它是私有的,那么你必须为它编写一个setter方法。


0
投票

我通过在 Storyboard 中取消选中视图控制器作为初始视图控制器并将以下代码添加到我的 AppDelegate 中来解决它:

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        let storybaord = UIStoryboard(name: "Main", bundle: Bundle.main)
        let initialVC = storybaord.instantiateViewController(withIdentifier: "ViewController") as! ViewController
        initialVC.networkService = NetworkService()
        
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = initialVC
        self.window?.makeKeyAndVisible()
        
        return true
    }
© www.soinside.com 2019 - 2024. All rights reserved.