I am writing one program on iOS and very race I am facing this error:
2015-11-06 10:57:24.289 NETFNET[2503:976392] CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null) 2015-11-06 10:57:24.293 NETFNET[2503:976392] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'
I am trying to access Data Base simultaneously, I think, from main and background threads. I have seen a lot of solutions for Objective C, but none for Swift (I don't know Objective C...). Unfortunately, I don't know how to work with Grand Central Dispatch and, in fact, my program does not really need several treads (I mean it need it, but if some thread loses info from one function for one time, nothing bad will happen). I just want to have stable program on Swift 1 or 2, so I will be thankful for any help.
You need to create a private NSManagedObjectContext with private queue concurrency type and use it to access CoreData whenever operating on a background thread.
So suppose I need to run a database operation on the background, I can dispatch that work to the background thread as
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
//call your background operation.
})
Then in the background operation I can create a private NSManagedObjectContext as
let moc = … //Our primary context on the main queue
let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = moc
privateMOC.performBlock {
//operations
do {
try privateMOC.save()
} catch {
fatalError("Failure to save context: \(error)")
}
}
Read through Apple's CoreData Concurrency Guide to get a good understanding before implementing core data operations on multiple threads.
Very good. I tried it, it worked fine for me. Thank you very much.
Previous Code:
do {
try CDHelper.shared.context.save()
}
catch let error as NSError {
// Error mesajlarını ekle!!
print("Could not fetch \(error), \(error.localizedDescription)")
print("Could not fetch \(error), \(error.localizedFailureReason)")
}
// MARK: - CONTEXT
lazy var context: NSManagedObjectContext = {
let moc = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
moc.persistentStoreCoordinator = self.coordinator
return moc
}()
// MARK: - MODEL
lazy var model: NSManagedObjectModel = {
return NSManagedObjectModel(contentsOfURL:self.modelURL)!
}()
// MARK: - COORDINATOR
lazy var coordinator: NSPersistentStoreCoordinator = {
return NSPersistentStoreCoordinator(managedObjectModel:self.model)
}()
lazy var modelURL: NSURL = {
let bundle = NSBundle.mainBundle()
if let url = bundle.URLForResource("Model", withExtension: "momd") {
return url
}
print("CRITICAL - Managed Object Model file not found")
abort()
}()
you should change the code this way:
let moc = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
let privateMOC = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext = moc
privateMOC.performBlock({
do {
try privateMOC.save()
} catch {
fatalError("Failure to save context: \(error)")
}
})
Just calling your CoreData Function inside
DispatchQueue.main.async {
...
}
worked for me
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With