【问题标题】:Trying to setup Core Data stack using Dependency Injection尝试使用依赖注入设置核心数据堆栈
【发布时间】:2018-02-11 07:15:35
【问题描述】:

我现在正在做一个使用 Core Data 的项目。但是,RootViewController 不使用它。我的应用程序中的第一个 ViewController 是注册或登录屏幕。只有在用户注册或登录后,他们才会被带到需要核心数据(因此需要 ManagedObjectContext)的应用程序的初始屏幕。我想使用的核心数据堆栈如下:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var persistentContainer: NSPersistentContainer!
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        createContainer { container in
            self.persistentContainer = container
            let storyboard = self.window?.rootViewController?.storyboard
            guard let vc = storyboard?.instantiateViewController(withIdentifier: "RootViewController") as? RootViewController
                else { fatalError("Cannot instantiate root view controller") }
            vc.managedObjectContext = container.viewContext
            self.window?.rootViewController = vc
        }
        return true
    }

    func createContainer(completion: @escaping (NSPersistentContainer) -> ()) {
        let container = NSPersistentContainer(name: "MyDataModel")
        container.loadPersistentStores { _, error in
           guard error == nil else { fatalError("Failed to load store: \(error)") }
           DispatchQueue.main.async { completion(container) }
        }
    }

}

我的问题是,我如何设置我的核心数据堆栈,并通过依赖注入绕过负责登录/注册的第一个视图控制器,并将 ManagedObjectContext 的值分配给 ViewController 的属性需要它(即 UITableViewController)?另外请记住,我没有使用情节提要,因此也需要修改上述方法以消除它的使用。

【问题讨论】:

  • 我假设您的意思是说您正在为 NSManagedObjects 使用依赖注入,以下是为什么这不是一种流行的做事方式的几个原因:stackoverflow.com/questions/43187929/… 而不是更喜欢延迟实例化的核心处理核心数据操作的数据单例类。这样想,当你可以为你的 NSManagedObject 写一个扩展来满足依赖时,你为什么要使用 DI。你应该尽量避免对你的 NSManagedObject 的任何外部依赖。
  • 将所有这些想法投入到配置 Core Data 中的意义何在,而不是 99.9% 的所有其他应用程序都这样做?只需在 App Delegate 中创建它并使用它配置第一个 View Controller。如果第一个 VC 不想使用它,它也不必。
  • 单例很糟糕,并且会创建难以维护的紧密耦合代码,几乎不可能测试并且很难重构。依赖注入解决了这些问题。延迟加载 Core Data 会导致性能下降。
  • 这在 Apple 的核心数据文档中有所介绍:developer.apple.com/documentation/coredata/... "将持久容器引用传递给视图控制器在应用程序的根视图控制器中,导入核心数据并创建一个变量来保存对持久容器的引用。返回到应用程序的委托。在 application(_:didFinishLaunchingWithOptions:) 中,将应用程序窗口的 rootViewController 向下转换为应用程序的根视图控制器类型。在此引用中,设置根视图控制器的容器属性到持久化容器。”

标签: ios swift core-data


【解决方案1】:
  1. 应用委托应将上下文(或上下文的容器)注入根视图控制器。
  2. 根视图控制器应将上下文注入其子视图。

即使根视图控制器不使用上下文并不意味着它不能负责依赖注入。

我会直接通过根视图控制器传递容器。

【讨论】:

  • 这意味着如果 rootViewController 是 UINavigationController 或 UITabBarController ,那么我们必须对它们进行子类化并在它们中添加上下文属性。对吗?
  • @AkshitZaveri 通常没有。我通常会编写逻辑来查找这两种情况,当发现它们时询问它们的根或视图控制器数组,然后将 MOC 传递到下一个级别。无需为那个用例子类化。
  • 这也是个好主意。因此,每个 UIViewController 实例都有一个 context 属性,然后可以将其传递给 ViewModels 以使用 CoreData API。
  • 好吧,我不会用枪指着我的头的视图模型,但你知道一般的想法是的:)
  • 视图控制器处理生命周期,视图处理显示,数据模型处理数据,其他任何东西进入适当的控制器(业务、网络等),依赖注入将所有东西绑定在一起。 KISS 原则适用 :) 聪明是坏事。
猜你喜欢
  • 2018-01-03
  • 2019-02-16
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多