Reputation: 1470
I am getting the following error while saving data to CoreData. I made this project completely simple for you to review my project. There is Local json in the project. You can download and test my project.
Project GitLab Link: Core Data Test Project
2021-08-20 20:17:03.576453+0300 CoreDataTest[27924:2275095] [error] warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'QuestionCD' so +entity is unable to disambiguate.
CoreData: warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'QuestionCD' so +entity is unable to disambiguate.
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'.
2021-08-20 20:17:03.576675+0300 CoreDataTest[27924:2275095] [error] warning: 'QuestionCD' (0x2809142c0) from NSManagedObjectModel (0x281d33ca0) claims 'QuestionCD'.
CoreData: warning: 'QuestionCD' (0x2809142c0) from NSManagedObjectModel (0x281d33ca0) claims 'QuestionCD'.
2021-08-20 20:17:03.576720+0300 CoreDataTest[27924:2275095] [error] warning: 'QuestionCD' (0x2809148f0) from NSManagedObjectModel (0x281d4cf50) claims 'QuestionCD'.
CoreData: warning: 'QuestionCD' (0x2809148f0) from NSManagedObjectModel (0x281d4cf50) claims 'QuestionCD'.
2021-08-20 20:17:03.576762+0300 CoreDataTest[27924:2275095] [error] warning: 'QuestionCD' (0x280914fd0) from NSManagedObjectModel (0x281d4e490) claims 'QuestionCD'.
CoreData: warning: 'QuestionCD' (0x280914fd0) from NSManagedObjectModel (0x281d4e490) claims 'QuestionCD'.
2021-08-20 20:17:03.576804+0300 CoreDataTest[27924:2275095] [error] error: +[QuestionCD entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
CoreData: error: +[QuestionCD entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
2021-08-20 20:17:03.585701+0300 CoreDataTest[27924:2275095] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-20 20:17:03.585897+0300 CoreDataTest[27924:2275095] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281028400
2021-08-20 20:17:03.586179+0300 CoreDataTest[27924:2275095] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-20 20:17:03.586297+0300 CoreDataTest[27924:2275095] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b0d5c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b0d5c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
2021-08-20 20:17:03.586383+0300 CoreDataTest[27924:2275095] [error] error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
2021-08-20 20:17:03.586553+0300 CoreDataTest[27924:2275095] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-20 20:17:03.586649+0300 CoreDataTest[27924:2275095] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281028400
2021-08-20 20:17:03.586799+0300 CoreDataTest[27924:2275095] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-20 20:17:03.586874+0300 CoreDataTest[27924:2275095] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b0d5c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b0d5c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
2021-08-20 20:17:03.586942+0300 CoreDataTest[27924:2275095] [error] error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
2021-08-20 20:17:03.587088+0300 CoreDataTest[27924:2275095] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-20 20:17:03.587163+0300 CoreDataTest[27924:2275095] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281028400
2021-08-20 20:17:03.587301+0300 CoreDataTest[27924:2275095] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-20 20:17:03.587372+0300 CoreDataTest[27924:2275095] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b0d5c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b0d5c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
2021-08-20 20:17:03.587434+0300 CoreDataTest[27924:2275095] [error] error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
2021-08-20 20:17:03.599299+0300 CoreDataTest[27924:2275095] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-20 20:17:03.599618+0300 CoreDataTest[27924:2275095] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281028400
2021-08-20 20:17:03.599908+0300 CoreDataTest[27924:2275095] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-20 20:17:03.600018+0300 CoreDataTest[27924:2275095] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b04000> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280b04000> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
Failed to save selected category: A Core Data error occurred.
Source Editor Functionality Is Limited Error (What is this ? / Why ?):
Core Data Entities:
Core Data Save Function:
func saveSelectedQuestion(questionTitle: String, id: String, questions: [QuestionList]) {
let questionsCD = QuestionCD(context: persistentContainer.viewContext)
questionsCD.title = questionTitle
questionsCD.id = id
questionsCD.questions = questions
do {
try persistentContainer.viewContext.save()
} catch {
print("Failed to save selected category: \(error.localizedDescription)")
}
}
Model:
class QuestionContainer: NSObject, Codable {
var questionCategories: [Question]
init(questionCategories: [Question]) {
self.questionCategories = questionCategories
}
}
class Question: NSObject, Codable {
var title: String
var id: String
var questions: [QuestionList]
init(title: String, id: String, questions: [QuestionList]) {
self.title = title
self.id = id
self.questions = questions
}
}
public class QuestionList: NSObject, Codable {
init(id: String, question: String, isQuestionImage: Bool, isSectionImage: Bool, imageURL: String, imageData: Data? = nil, sections: Sections, selected: String, correct: String) {
self.id = id
self.question = question
self.isQuestionImage = isQuestionImage
self.isSectionImage = isSectionImage
self.imageURL = imageURL
self.imageData = imageData
self.sections = sections
self.selected = selected
self.correct = correct
}
var id: String
var question: String
var isQuestionImage, isSectionImage: Bool
var imageURL: String
var imageData: Data?
var sections: Sections
var selected: String
var correct: String
}
public class Sections: NSObject, Codable {
init(a: String, b: String, c: String, d: String) {
self.a = a
self.b = b
self.c = c
self.d = d
}
var a, b, c, d: String
private enum CodingKeys: String, CodingKey {
case a = "A"
case b = "B"
case c = "C"
case d = "D"
}
}
Page Where I Save Data:
I am saving data from this page.
struct QuestionCategoryCellView: View {
@ObservedObject var questionCategoryCellViewModel = QuestionCategoryCellViewModel()
var questionTitle: String
var questionID: String
@Binding var questions: [QuestionList]
var body: some View {
Button(action: {
print("title: \(questionTitle)")
if questionCategoryCellViewModel.searchCategoryInCoreData(id: questionID) {
print("already saved")
} else {
questionCategoryCellViewModel.saveSelectedQuestionsToCoreData(questionTitle: questionTitle, id: questionID, questions: questions)
}
}) {
Text(questionTitle)
}
}
}
Upvotes: 5
Views: 2941
Reputation: 1561
I had a similar error but the solutions was different. If you come across this post but the accepted answer does not solve your problem, maybe you need to separate your local and remote database models.
I was using the NSPersistentCloudKitContainer
and all entities were syncing across devices (with the same iCloud id). But then, I decided not to sync particular entities. This was a business decision. So I created a separate container of type NSPersistentContainer
and expected it to keep one type of entity locally, and others on iCloud. This is when I got the errors mentioned above.
After hours of digging I tried to separate local and iCloud models and it worked.
Upvotes: 0
Reputation: 405
ALL RIGHTS GO TO @TOM HARRINGTON.
I have been looking for an answer to this problem for 6 hours!!!!
However, instead of:
let coreDM: CoreDataManager = CoreDataManager.shared
I used:
@StateObject var coreDM: CoreDataManager = CoreDataManager.shared
Tom, I could kiss you.
Upvotes: 0
Reputation: 70936
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,
You create a QuestionCategoryCellView
QuestionCategoryCellView
creates a QuestionCategoryCellViewModel
Every instance of QuestionCategoryCellViewModel
has this property:
let coreDM: CoreDataManager = CoreDataManager()
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
Add this line to CoreDataManager
:
static var shared = CoreDataManager()
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.
Upvotes: 9