在 MVVM 应用程序中访问核心数据堆栈
Posted
技术标签:
【中文标题】在 MVVM 应用程序中访问核心数据堆栈【英文标题】:Accessing Core Data Stack in MVVM application 【发布时间】:2020-05-03 09:02:18 【问题描述】:我正在使用MVVM
模式编写应用程序。我想知道如何创建 CoreData
堆栈,以便可以从我的应用程序中的各个位置访问它。
第一种方法是在AppDelegate
中创建一个持久容器,然后将此服务注入我的 ViewModel(同时将managedObjectContext
作为环境变量传递给我的 View)。
但是,通过这种方式访问整个应用程序的上下文更加困难:例如在解码网络响应时,因为他们无权访问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()
我见过的另一个解决方案是使用单例。我可以从项目中的任何位置访问它,但我如何以正确的方式创建它?
如果我不想同时修改 main 和 background 队列中的某个对象怎么办?或者如果两个队列都想修改同一个对象怎么办?
【问题讨论】:
不是一个实际的答案,而是思考的食物:恕我直言,在解码网络响应时使用核心数据不是正确的方法。我宁愿使用DTOs,然后将转换和存储它们的责任留给其他人。 对于那些想知道如何将上下文注入 View 和 View Model,***.com/q/63959960/2226315 【参考方案1】:你可以使用 Core Data Singleton 类
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 上写了一些东西并且不想保存它,但是其他一些线程保存了上下文,那么你不想保留的更改也会保留。
因此,为了避免这种情况,请始终创建工作上下文 - 这是私有的。
当你按下保存时,第一个私有上下文被保存,然后你保存主上下文。
在 MVVM 中,您应该有 DataLayer,您的 ViewModel 通过它与 Core Data 单例类进行交互。
【讨论】:
我们如何在 SwiftUI 中使用它?您是仅通过 EnvironmentObject 传递上下文还是传递整个 CoreDataStack?谢谢!以上是关于在 MVVM 应用程序中访问核心数据堆栈的主要内容,如果未能解决你的问题,请参考以下文章