Search code examples
iosswiftnsmanagedobjectdecodable

Fetch request required after decoding into a NSManagedObject object


I have the following generic function that works: it correctly creates the objects and I know is saved into core data because if do a fetch request right after, I get the object I just created. However, the object itself isn't a valid core data object (x-core data fault). Is there any way around so I don't have to do a fetch request right after a decoding an object? Many thanks.

func decode<T: Decodable>(data: Data?, objectType: T.Type, save: Bool = true, completionHandler: @escaping (T) -> ())
{
    guard let d = data else { return }
    do
    {
        let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        privateContext.parent = SingletonDelegate.shared.context

        let root = try JSONDecoder(context: privateContext).decode(objectType, from: d)

        if save
        {
            try privateContext.save()
            privateContext.parent?.performAndWait
            {
                do
                {
                    if let p = privateContext.parent
                    {
                        try p.save()
                    }

                }catch
                {
                    print(error)
                }
            }
        }
        DispatchQueue.main.async
        {
            completionHandler(root)
        }
    }catch
    {
        print(error)
    }
}

extension CodingUserInfoKey 
{
    static let context = CodingUserInfoKey(rawValue: "context")!
}


extension JSONDecoder 
{
    convenience init(context: NSManagedObjectContext) 
    {
        self.init()
        self.userInfo[.context] = context
    }
}

Solution

  • A core data fault is a valid Core Data object; it just hasn't been retrieved from the backing store into memory yet.

    To reduce memory use, Core Data only fetches the full object when you access one of its properties. This fetch is automatic and effectively transparent to your code.

    This means you don't need to do anything special; you can just use the managed object.