The only way you can ensure uniqueness would be to have a coordinating object that all contexts turn to to verify their operation (a "uniqueness enforcer" if you will).
The general algorithm is described HERE, however you fall under the "multi-threaded/context" category and this will complicate things.
In a multi-threaded environment, your enforcer would have to perform a save to the store (using its own managed object context) before returning results to the calling object.
The general flow would be (no cache version):
- A context request object for keys from the enforcer
- The enforcer issue the request "under lock" (either locking an actual lock or using a serial dispatch queue)
- the enforcer query the store for existing objects
- create objects for missing keys and save them
- you might want to mark the objects as stubs, as the caller might not eventually save and it will give you a flag to ignore them in your fetch requests in your views
- build the results array with the objects he created
- the results might be
NSManagedObjectID
s or imported objects in the caller context otherwise you risk cross context access of managed objects