在 MVVM 应用程序中访问核心数据堆栈 [英] Accessing Core Data Stack in MVVM application

查看:14
本文介绍了在 MVVM 应用程序中访问核心数据堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 MVVM 模式编写应用程序.我想知道如何创建 CoreData 堆栈,以便可以从我的应用程序的各个位置访问它.

I'm writing an application using the MVVM pattern. And I'm wondering know how to create the CoreData stack so it can be accessed from various places in my app.

第一种方法是在 AppDelegate 中创建一个持久容器,然后将此服务注入我的 ViewModel(同时将 managedObjectContext 作为环境变量传递给我的视图).

First approach is to create a persistent container in the AppDelegate and then inject this service to my ViewModels (simultaneously passing the managedObjectContext as an environment variable to my Views).

然而,通过这种方式,访问整个应用程序的上下文更加困难:例如在解码网络响应时,因为它们无权访问 managedObjectContext:

This way, however, accessing context throughout the app is more difficult: e.g. in decoding network responses, as they don't have access to the managedObjectContext:

protocol APIResource {
    associatedtype Response: Decodable
    ...
}

extension APIResource {
    func decode(_ data: Data) -> AnyPublisher<Response, APIError> {
        Just(data)
            // how can I access context here to pass it to JSONDecoder?
            .decode(type: Response.self, decoder: JSONDecoder())
            .mapError { error in
                .parsing(description: error.localizedDescription)
            }
            .eraseToAnyPublisher()
    }
}

我见过的另一个解决方案是使用单例.我可以从项目的任何地方访问它,但我如何以正确的方式创建它?

The other solution I've seen is to use a singleton. I can access it from anywhere in the project but how can I create it in the right way?

如果我不想同时修改 mainbackground 队列中的某个对象怎么办?或者如果两个队列都想修改同一个对象怎么办?

What if I wan't to modify some object in the main and the background queue at the same time? Or what if both queues want to modify the same object?

推荐答案

可以使用 Core Data Singleton 类

You can use Core Data Singleton class

import CoreData

class CoreDataStack {
    static let shared = CoreDataStack()

    private init() {}

    var managedObjectContext: NSManagedObjectContext {
        return self.persistentContainer.viewContext
    }

    var workingContext: NSManagedObjectContext {
        let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        context.parent = self.managedObjectContext
        return context
    }

    // MARK: - Core Data stack

    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "MyStuff")
        container.loadPersistentStores(completionHandler: { storeDescription, error in
            if let error = error as NSError? {
                RaiseError.raise()
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext() {
        self.managedObjectContext.performAndWait {
            if self.managedObjectContext.hasChanges {
                do {
                    try self.managedObjectContext.save()
                    appPrint("Main context saved")
                } catch {
                    appPrint(error)
                    RaiseError.raise()
                }
            }
        }
    }

    func saveWorkingContext(context: NSManagedObjectContext) {
        do {
            try context.save()
            appPrint("Working context saved")
            saveContext()
        } catch (let error) {
            appPrint(error)
            RaiseError.raise()
        }
    }
}

Core Data 不是线程安全的.如果你在 manageObject 上写了一些东西并且不想保存它,但其他一些线程保存了上下文,那么你不想持久化的更改也会持久化.

Core Data is not thread safe. If you write something on manageObject and don't want to save that, but some other thread save the context, then the changes that you don't want to persist will also persist.

因此,为了避免这种情况,请始终创建工作上下文 - 这是私有的.

So to avoid this situation always create working context - which is private.

当您按保存时,首先保存私有上下文,然后保存主上下文.

When you press save, then first private context get saved and after that you save main context.

在 MVVM 中,您应该拥有 DataLayer,您的 ViewModel 通过它与 Core Data 单例类进行交互.

In MVVM you should have DataLayer through which your ViewModel interact with Core Data singleton class.

这篇关于在 MVVM 应用程序中访问核心数据堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆