无法在自己的商店之外使用参考,背景和主要上下文问题来保存对象
我有一个核心数据存储。我想要的是在背景上下文中执行保存,并在主要上下文中获取。因此,我拥有以下coredatastack
的设置,该设置处理核心数据中的保存/获取:
class CoreDataStack {
static let modelName = "Model"
static let managedObject: NSManagedObjectModel = {
guard let modelUrl = Bundle.module.url(
forResource: "Model",
withExtension: "momd"
) else {
return .init()
}
return NSManagedObjectModel(contentsOf: modelUrl) ?? .init()
}()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(
name: Self.modelName,
managedObjectModel: Self.managedObject
)
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
dispatchGroup.leave()
})
dispatchGroup.wait()
return container
}()
lazy var backgroundContext: NSManagedObjectContext = {
let context = persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
return context
}()
lazy var mainContext: NSManagedObjectContext = {
let mainContext = persistentContainer.viewContext
mainContext.automaticallyMergesChangesFromParent = true
mainContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
return mainContext
}()
func fetch<Item: NSManagedObject>(
_ request: NSFetchRequest<Item>
) -> [Item] {
do {
let items = try self.mainContext.fetch(request)
return items
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
return []
}
}
func saveContext() {
backgroundContext.perform {
do {
try self.backgroundContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
}
}
我有一个nsmanagedObject
叫做takenedbar
。这包含data
属性,该属性是另一个nssordedset
的 nsmanagedObject nsmanagedObject nassedfoo take> mawsedfoo 。
我有一个函数savefoo(_:)
在背景上下文上创建MANGEDFOO
,请求a a
在前景上下文中,然后如果那样托管bar
存在,将其添加到takanedfoo
数据中。然后保存了背景上下文:
func saveFoo(_ Foo: Foo) {
let managedFoo = ManagedFoo(
context: coreDataStack.backgroundContext,
name: foo.name,
)
let request = ManagedBar.fetchRequest()
request.predicate = NSPredicate(format: "name == %@", foo.name)
if let bar = coreDataStack.fetch(request).first {
bar.addToData(managedFoo)
} else {
let event = ManagedBar(
context: self.coreDataStack.backgroundContext,
name: foo.name
)
self.coreDataStack.saveContext()
}
}
我还具有一个函数来检索takandbar
的所有name
属性,它从主要上下文中获取所有内容:
func getAllBarNames() -> [String] {
let fetchRequest = ManagedEvent.fetchRequest()
let eventData = coreDataStack.fetch(fetchRequest)
let names = eventData.map { $0.name }
return names
}
然后,当我运行以下时代码,它在大多数情况下起作用,但有时会失败:
func testGetAllEventNames() {
let foo1 = Foo()
saveFoo(foo1)
let foo2 = Foo()
saveFoo(foo2)
let names = getAllBarNames()
print(names)
}
这有时可以正常工作,但有时由于两个原因之一而失败:
无法在自己的商店外用参考保存对象。
collection&lt; __NSCFSET:0x6000031407b0&gt; 在枚举时被突变。
(这发生在第二个savefoo
)时, 即使我在单元测试中运行此代码并等待nsmanageBjectContextDidsave
通知,这些错误即使在调用getAllBarnames()
之前,
也必须等待这些错误。不完全确定什么。有人知道这里出了什么问题吗?
I have a core data store. What I want is to perform saves in a background context, and fetches on the main context. So I have the following setup of CoreDataStack
that handles the saving/fetching in the core data:
class CoreDataStack {
static let modelName = "Model"
static let managedObject: NSManagedObjectModel = {
guard let modelUrl = Bundle.module.url(
forResource: "Model",
withExtension: "momd"
) else {
return .init()
}
return NSManagedObjectModel(contentsOf: modelUrl) ?? .init()
}()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(
name: Self.modelName,
managedObjectModel: Self.managedObject
)
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
print("Unresolved error \(error), \(error.userInfo)")
}
dispatchGroup.leave()
})
dispatchGroup.wait()
return container
}()
lazy var backgroundContext: NSManagedObjectContext = {
let context = persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
return context
}()
lazy var mainContext: NSManagedObjectContext = {
let mainContext = persistentContainer.viewContext
mainContext.automaticallyMergesChangesFromParent = true
mainContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
return mainContext
}()
func fetch<Item: NSManagedObject>(
_ request: NSFetchRequest<Item>
) -> [Item] {
do {
let items = try self.mainContext.fetch(request)
return items
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
return []
}
}
func saveContext() {
backgroundContext.perform {
do {
try self.backgroundContext.save()
} catch let error as NSError {
print("Unresolved error \(error), \(error.userInfo)")
}
}
}
}
I have an NSManagedObject
called ManagedBar
. This contains a data
property which is an NSSOrderedSet
of another NSManagedObject
called ManagedFoo
.
I have a function saveFoo(_:)
which creates a ManagedFoo
on the background context, requests a ManagedBar
in the foreground context, then if that ManagedBar
exists, adds it to the ManagedFoo
to data
. Then the background context is saved:
func saveFoo(_ Foo: Foo) {
let managedFoo = ManagedFoo(
context: coreDataStack.backgroundContext,
name: foo.name,
)
let request = ManagedBar.fetchRequest()
request.predicate = NSPredicate(format: "name == %@", foo.name)
if let bar = coreDataStack.fetch(request).first {
bar.addToData(managedFoo)
} else {
let event = ManagedBar(
context: self.coreDataStack.backgroundContext,
name: foo.name
)
self.coreDataStack.saveContext()
}
}
I also have a function to retrieve all the name
properties of ManagedBar
which fetches them all from the main context:
func getAllBarNames() -> [String] {
let fetchRequest = ManagedEvent.fetchRequest()
let eventData = coreDataStack.fetch(fetchRequest)
let names = eventData.map { $0.name }
return names
}
Then, when I run the following code, it works most of the time but sometimes fails:
func testGetAllEventNames() {
let foo1 = Foo()
saveFoo(foo1)
let foo2 = Foo()
saveFoo(foo2)
let names = getAllBarNames()
print(names)
}
This sometimes works fine, but other times fails for one of two reasons:
Cannot save objects with references outside their own stores.
Collection <__NSCFSet: 0x6000031407b0> was mutated while being enumerated.
(this occurs on the secondsaveFoo
)
Other times, names
doesn't contain all the names that I've saved. These errors happen even if I run this code in a unit test and wait for the NSManagedObjectContextDidSave
notification before calling getAllBarNames()
This must be caused by some background/main context issue but not entirely sure what. Does anyone know what's going wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论