SwiftedMind
SwiftedMind

Reputation: 4287

Does managedObjectContext.object(with:) always refetch data if another (private) managedObjectContext changed and saved it?

(I'm sorry if this question is kind of confusing/imprecise. I'm just learning advanced CoreData usage and I don't know the terminology and stuff very well).

I have a singleton Game that holds certain data you need during the game. For example, you can access currentSite (Site is a CoreData Entity) from there to get the Site the user is currently at:

// I created the Site in a background queue (when the game started), then saved the objectID and here I load the objectID
public var currentSiteObjectID: NSManagedObjectID {
        let objectIDuri = UserDefaults.standard.url(forKey: Keys.forGameObject.currentSiteObjectIDURI)!
        return appDelegate.persistentContainer.persistentStoreCoordinator.managedObjectID(forURIRepresentation: objectIDuri)!
    }

// managedObjectContext is the one running on the main queue    
public var currentSite: Site! {
        return managedObjectContext.object(with: currentSiteObjectID) as! Site
    }

You see, I retrieve the currentSite by using the managedObjectContext.object(with:) method.

The documentation of this method says:

Returns the object for a specified ID.

If the object is not registered in the context, it may be fetched or returned as a fault. (...)

I'm not quite sure about the following:

// Each Site has resources that you can access like this
print(Game.shared.currentSite!.resourceSet!.iron)

appDelegate.persistentContainer.performBackgroundTask { (context) in
    let currentSite = context.object(with: Game.shared.currentSiteObjectID) as! Site

    // Here I increase the iron resource
    currentSite.resourceSet!.iron += 42
    do {
        try context.save()
    } catch let error as NSError {
        fatalError("\(error.debugDescription)")
    }

    DispatchQueue.main.async {
        print(Game.shared.currentSite!.resourceSet!.iron)
    }
}

The second print function is using the managedObjectContext of the main queue (which is different to the private one used inside performBackgroundTask {...}).

It actually does print:

50 // the start value
92 

My question: Is it guaranteed that managedObjectContext.object(with:) returns the current object (that is up-to-date), even if it has been changed in another context? The documentation says that it will be fetched if it's a new object that's not known to the context. But what if an object changes?

I'm not sure if it's just a coincidence that the example code from above is working like expected.

Thanks for any help/explanation! I'm eager to learn about this kind of stuff.

Upvotes: 3

Views: 69

Answers (1)

Mateusz
Mateusz

Reputation: 1224

No it is not guaranteed. If managed object is already registered in context then it will return this object. What's more, if object with given id (NSManagedObjectId) doesn't exist in persistent store then your app will crash as soon as you try to use any of its properties.

Upvotes: 1

Related Questions