[Core Data]: Threw While Encoding a Value. with Userinfo of (Null)

Core Data Encoding Crash On Saving Context

It looks like you're trying to use this type as a Core Data transformable attribute.
Core Data transformable attributes must conform to NSCoding. Codable has a similar name and a similar purpose, but they are not the same and are not compatible with each other. If you want to use this type with a Core Data transformable attribute, it must conform to NSCoding.

CoreData with transformable attribute fails on save

A transformable attribute requires a class conforming to NS(Secure)Coding (not Codable!) and the implementation of archiving the object(s). Note the NSSecureUnarchiveFromData errors.

In the Swift world consider to declare the attribute as String, encode the object to JSON with Codable and add a computed property for the seamless conversion.

CoreData - Store an array of Tranformable objects

If you are going to unarchive an array you have to add NSArray to the top level classes, this is how I understand the error message

override class var allowedTopLevelClasses: [AnyClass] {
return [NSArray.self, Reminder.self]
}

By the way, instead of a transformable consider to encode the array to JSON and save it as a simple String. The conversion can be performed by a computed property.

The class can be a struct with dramatically less code

public struct Reminder : Codable {
public var date: Date
public var isOn: Bool
}

In the NSManagedObject subclass create a String Attribute

@NSManaged public var cdReminders : String

and a computed property

var reminders : [Reminder] {
get {
return (try? JSONDecoder().decode([Reminder].self, from: Data(cdReminders.utf8))) ?? []
}
set {
do {
let reminderData = try JSONEncoder().encode(newValue)
cdReminders = String(data: reminderData, encoding:.utf8)!
} catch { cdReminders = "" }
}
}

[Core Data]:Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Core Data Model' so +entity is unable to disambiguate

In your error messages there are four message pairs like this:

2021-08-20 20:17:03.576623+0300 CoreDataTest[27924:2275095] [error] warning:     'QuestionCD' (0x28090c9a0) from NSManagedObjectModel (0x281d3d400) claims 'QuestionCD'.
CoreData: warning: 'QuestionCD' (0x28090c9a0) from NSManagedObjectModel (0x281d3d400) claims 'QuestionCD'.

But if you look closely, the memory address of the model is different every time. It's 0x281d3d400 here, and it's different the other three times. That's because there are four different copies of the managed object model in memory. You're loading the model more than once and confusing Core Data. It's the same entity, but Core Data is confused about where to use it.

Looking at your code, this happens because for every cell in your table,

  1. You create a QuestionCategoryCellView

  2. QuestionCategoryCellView creates a QuestionCategoryCellViewModel

  3. Every instance of QuestionCategoryCellViewModel has this property:

    let coreDM: CoreDataManager = CoreDataManager()
  4. Every CoreDataManager calls persistentContainer.loadPersistentStores.

As a result, every cell loads the persistent container. That should never happen. You have four cells, and every cell has its own persistent container, and each container has its own copy of the model.

Either your CoreDataManager or the persistentContainer need to be created only once, and then used for every cell. I'd say to go for a singleton CoreDataManager but either would probably work.

One easy way to do that is to

  1. Add this line to CoreDataManager:

    static var shared = CoreDataManager()
  2. Change QuestionCategoryCellViewModel so that instead of creating a CoreDataManager, it does this:

    let coreDM: CoreDataManager = CoreDataManager.shared

If you do that, you'll avoid this problem.

You will however run into a completely different bug in your code. Your data model uses [QuestionList] as the type for a transformable attribute. But QuestionList doesn't conform to NSCoding, so that doesn't work an the app crashes. Ask a different question here about that.

Core Data exception error - Invalid fetch request: HAVING with no GROUP BY with userInfo of (null)

You are using a standard query without a GROUP BY directive – that's what the error says – so use the standard API

request.predicate = predicate

And you can get rid of the type cast and the type annotation if you specify the generic type of the request

let request = NSFetchRequest<Affirmation>(entityName: CoreDataStrings.entityAffirmation)

...

let affirmationEntityInstances = try managedObjectContext.fetch(request)


Related Topics



Leave a reply



Submit