如何使用 NSManagedObjectContext 的 func assign(_ object: Any, to store: NSPersistentStore)?

How to use func assign(_ object: Any, to store: NSPersistentStore) of a NSManagedObjectContext?

设置:
我的应用程序使用由多个托管对象上下文使用的单个持久存储协调器管理的 2 个持久存储。两个持久存储存储相同的实体。
要求托管对象的任何插入、更新和删除仅在两个持久存储之一中完成,并且应用程序可以 select 持久存储。

问题:
为了仅将托管对象存储在一个持久存储中,我想使用 NSManagedObjectContextfunc assign(_ object: Any, to store: NSPersistentStore)docs

Specifies the store in which a newly inserted object will be saved.

问题:
“新插入”是什么意思?

当应用程序切换持久存储时,我会重置上下文,以便新获取所有托管对象,并且可以在 willSaveObjectsNotification 通知中再次设置所需的持久存储。
这是正确的方法吗?

该函数只能用于不属于任何托管对象上下文的托管对象。可以使用不属于任何上下文的实体描述来创建实例。例如,您可以使用 init(entity:,insertInto:) 和 nil 作为第二个参数。如果这样做,您稍后可以使用 `assigns 函数将其插入到上下文中。

如果托管对象已经与上下文相关联,则不能使用此功能将其移动到另一个上下文。您需要在新上下文中创建一个新实例并复制所有 属性 值。

根据 Tom Harrington 的回答,我做了以下测试。
结果是:
只要托管对象从未保存到持久存储中,就可以使用 assign(_:to:) 定义稍后将对象保存到的几个持久存储之一。

我的代码:

// Setup:
// privateStore and sharedStore are persistent stores to which the Item entity is assigned.
// Item is a managed object whose entity is assigned to the persistent stores privateStore and sharedStore.
// It has an attribute "name" to distibguish it from other objects.

// Create for privateStore and sharedStore one fetch request respectively for an Item with name "item"
let namePredicate = NSPredicate(format: "name == %@", "item")

let privateStoreItemFetchRequest = NSFetchRequest<Item>(entityName: Item.entityName)
privateStoreItemFetchRequest.predicate = namePredicate
privateStoreItemFetchRequest.affectedStores = [privateStore]

let sharedStoreItemFetchRequest = NSFetchRequest<Item>(entityName: Item.entityName)
sharedStoreItemFetchRequest.predicate = namePredicate
sharedStoreItemFetchRequest.affectedStores = [sharedStore]

// 1st test: Create an Item without a context, assign it to a store, insert it into a context and try to fetch it from both stores
let item1 = Item(entity: itemEntity, insertInto: nil)
item1.name = "item"
viewContext!.assign(item1, to: privateStore)
viewContext!.insert(item1)
let items1InPrivateStore = try? viewContext!.fetch(privateStoreItemFetchRequest)
print("Test 1: privateStore: \(items1InPrivateStore ?? [])") // Prints item1
let items1InSharedStore = try? viewContext!.fetch(sharedStoreItemFetchRequest)
print("Test 1: sharedStore: \(items1InSharedStore ?? [])") // Prints []

// 2nd test: Create an Item and insert it into a context, assign it to a store and try to fetch it from both stores
let item2 = Item(entity: itemEntity, insertInto: viewContext!)
item2.name = "item"
viewContext!.assign(item2, to: privateStore)
let items2InPrivateStore = try? viewContext!.fetch(privateStoreItemFetchRequest)
print("Test 2: privateStore: \(items2InPrivateStore ?? [])") // Prints item1 and item2
let items2InSharedStore = try? viewContext!.fetch(sharedStoreItemFetchRequest)
print("Test 2: sharedStore: \(items2InSharedStore ?? [])") // Prints []

// Save the context and try to fetch both items from both stores
do {
    try viewContext!.save()
} catch { fatalError() }
let items3InPrivateStore = try? viewContext!.fetch(privateStoreItemFetchRequest)
print("Test 3: privateStore: \(items3InPrivateStore ?? [])") // Prints item1 and item2
let items3InSharedStore = try? viewContext!.fetch(sharedStoreItemFetchRequest)
print("Test 3: sharedStore: \(items3InSharedStore ?? [])") // Prints []

// item1 has been assigned above to the privateStore. Try now to assign it to the sharedStore
viewContext!.assign(item1, to: sharedStore) // Run time error: "Can't reassign an object to a different store once it has been saved."