Signature of NSManagedObjectContext perform

Hi all, I am running into an oddity with the NSManagedObjectContext perform method and want to see if anyone else has run into this/agrees with my thoughts. Or perhaps on the other hand, you can explain why I'm mistaken :slight_smile:

I would like to do something like this:

var result: Entity?

try await self.context.perform {
    let decoder = JSONDecoder()
    decoder.userInfo[.managedObjectContext] = context
    result = try decoder.decode(Entity, from: Data)
}

return result

However, the block passed to perform is escaping, so I cannot do this. What I don't understand is why perform is both async and has an escaping closure. It seems to me like it should either be async and not escaping, allowing me to use it as I'm attempting to do above or should not be async and take an escaping closure with the ability to bridge it to an async context with a continuation. Can someone help shed some light on what I'm missing?

I know I could use performAndWait instead to achieve this result, but I would prefer if I didn't have to block the calling thread.

I haven't used Core Data in a while, but the async variant of NSManagedObjectContext.perform returns the closure's return value to its own caller, so you should be able to write this:

let result: Entity = try await self.context.perform {
    let decoder = JSONDecoder()
    decoder.userInfo[.managedObjectContext] = context
    return try decoder.decode(Entity.self, from: data)
}

(Note: I removed the optionalness of result: Entity? because it made more sense to me this way. And I made some other changes in the decoder.decode line: Entity.self; data instead of Data.)

3 Likes

Ah, I didn't realize you could return a value from the closure that way. This is just what I needed, thank you!

And yes, thank you for the updates. I was translating this to be more generic from my code and made some mistakes which your updates corrected :slight_smile:

Yeah, it's nice API design. For what it's worth, many standard library APIs use the same pattern. For example: