I have came across 2 demo CoreData projects, which involves transaction history.
Both are using
viewContext.setQueryGenerationFrom(.current)
when they initialize their CoreData stack.
FireballWatch demo from raywenderlich
The demo is picked from https://www.raywenderlich.com/14958063-modern-efficient-core-data
The author is trying to demonstrate, how to make use of transaction history, to update UI correctly after batch insertion.
However, it isn’t clear on what problem viewContext.setQueryGenerationFrom(.current)
is trying to solve.
Brief explanation of the article https://www.raywenderlich.com/14958063-modern-efficient-core-data doesn’t tell much about the idea behind setQueryGenerationFrom
.
You are pinning the view context to the most recent transaction in the
persistent store with the call to setQueryGenerationFrom(_:). However,
because setting query generation is only compatible with an SQLite
store, you do so only if inMemory is false.
Synchronizing a Local Store to the Cloud from Apple
The demo is picked from https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud
It is trying to demonstrate, how to use transaction history, to prevent data duplication after syncing with CloudKit.
However, it is still not clear on what problem viewContext.setQueryGenerationFrom(.current)
is trying to solve.
Not much explanation is given behind the idea on setQueryGenerationFrom
.
Experiment
No matter whether I have included viewContext.setQueryGenerationFrom(.current)
, or excluded viewContext.setQueryGenerationFrom(.current)
in my CoreData stack, I am having the same observation in both situations.
- Able to observe UI update immediately, after I save a new
NSManagedObject
, withcontext.save
called. - Able to observe UI update immediately, after I edit an existing
NSManagedObject
, withcontext.save
called. - Able to observe UI update immediately, after I perform batch
NSBatchUpdateRequest
operation, withmergeChanges
called. - Able to observe UI update immediately, after I perform batch
NSBatchDeleteRequest
operation, withmergeChanges
called.
There are some good graphical explanation on what is doing by setQueryGenerationFrom
https://cocoacasts.com/what-are-core-data-query-generations
However, I fail to relate it to, what kind of real problem setQueryGenerationFrom
is trying to solve.
Does anyone know, what problem viewContext.setQueryGenerationFrom is trying to solve in CoreData project which involves transaction history? Would be appreciate, if there is a solid demo code example, to show what kind of problem is solved by setQueryGenerationFrom. Thank you.
2
Answers
It just pins some snapshot of context, so all your following queries work with exactly that snapshot, independently of what’s happened after pin-moment. It’s like detached checkout from GitHub – everyone goes ahead but you work with out sandbox.
This is guaranty of consistency which could be needed for some sequence of requests between which no changes should happen.
To pin we use
viewContext.setQueryGenerationFrom(.current)
To unpin and continue with kind-of-HEAD we use
viewContext.setQueryGenerationFrom(nil)
Additional description is in Apple’s article
Taking the demo project CoreDataCloudKitDemo, it is to support the case where device1 is editing a post, and device2 deletes it. You can take look for this piece of code:
With the magic of query generation, we will be able to immediately pop up this alert on the device1 which is editing the post, after device2 device deletes it.
On the main listing view, there are no issues, as the item will probably just be animated out of the list. The issue is for the details view, what is going to be shown, and what happens if the user edits the value the details view.
In samples codes, this is usually following
As in the details view, usually we will be holding on to an object, and once it is deleted, the object itself should become invalid, and accessing it or the attributes will cause unexpected behaviours.