Search code examples
ioscore-datansmanagedobjectcontext

How to access NSManagedObject entity using objectID which is not saved yet in iOS?


I have created one entity using private queue MOC and called performBlock() to save it asynchronously.

Let’s say I want this newly created entity in other context / MOC, so I have only one way to access it is use object id.
But as it’s asynchronous call to save entity, it is possibility of situation where entity is not saved yet and I want to access it immediately after performBlock(), but on other context.

What is the way to access it in this situation?

Thanks in advance!


Update

let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = mainThreadManagedObjectContext()

let newUser = Contact(nameStr: "name", moc: privateMOC)

This is my generic code to create new entities like:

init(nameStr: String,  moc:NSManagedObjectContext) {
        let mEntity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: moc)
        super.init(entity: mEntity!, insertIntoManagedObjectContext: moc)
    name = nameStr
}

After creating, I am saving it immediately as:

performBlock { () -> Void in
            do {
                try privateMOC.save()
            }catch {
                fatalError("Error asynchronously saving private moc - \(errorMsg): \(error)")
            }
        }

//accessing

let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = mainThreadManagedObjectContext()

let pred = NSPredicate(format: "name == %@", "name")
if let results = DatabaseInterface.sharedInstance.fetchEntityFromCollection("Contact", withPredicate: pred, moc: privateMOC) {
            if let user = results.last {
                return user as! Contact
            }
        }
else {
            DDLogWarn("No user found")
        }

I am not getting any user, but I can see this new contact is saved in DB when look using sqlitebrowser

Forgive me for indentation of code :(


Solution

  • What you're asking is impossible.

    When you create a managed object on one context, it only exists in memory until you save changes. No other managed object context can get to it, even if you use the object ID. The other context can't look up the data from the persistent store file, and it can't get it from the other context. It can't get the object at all. You need to wait until the save completes.

    A couple of things you might try, depending on how your app is structured:

    • Use performBlockAndWait instead of performBlock, so that you'll know that the save has completed by the time the block finishes.
    • Keep using performBlock but put calls inside that block that lead to accessing the object on a different context-- via a nested performBlock call on that other context.