slimboy slimboy - 2 months ago 90
iOS Question

(SWIFT 3) parent child context crash core data (libc++abi.dylib: terminating with uncaught exception of type NSException (Recorded Frame) )

I'm trying to save messages on the background queue and push them to the main queue by using two contexts a parent and a child. but my app keeps crashing. I used apples docs, not sure why its not working...

Core Data, Multithreading, and the Main Thread

here is my code:

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

let privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)


let doubletimestamp = Double(timestamp)
let date = Date(timeIntervalSinceReferenceDate: (doubletimestamp))
let status = "..."

let message = NSEntityDescription.insertNewObject(forEntityName: "Mesages", into: self.privateMOC) as! Mesages
message.text = text
message.timestamp = date as NSDate

do {
try self.privateMOC.save()
self.inputToolbar.toggleSendButtonEnabled()

self.context.performAndWait {

do {
try self.context.save()
} catch {
fatalError("Failure to save context: \(error)")
}

}

}catch let err {
print(err)
}

}


also here is my stacktrace:
enter image description here

Answer

Ok so there are two problems you have.

The first is that you haven't set the parent context. If you don't do this nothing will be propagated to your main managed context

The second is that you are not changing the private managed context in it's own block. In the same way that your normal managed context needs to be run (which you have done) the private context needs to do the same.

So the finished code should look like this:-

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

let privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)

private.parentContext = context

let doubletimestamp = Double(timestamp)
let date = Date(timeIntervalSinceReferenceDate: (doubletimestamp))
let status = "..."

privateMOC.performBlock {

    let message = NSEntityDescription.insertNewObject(forEntityName: "Mesages", into: self.privateMOC) as! Mesages
    message.text = text
    message.timestamp = date as NSDate        

    do {
        try self.privateMOC.save()
        self.inputToolbar.toggleSendButtonEnabled()

        self.context.performAndWait {

            do {
                try self.context.save()
            } catch {
                fatalError("Failure to save context: \(error)")
            }

        }

    }catch let err {
        print(err)
    }

    }
}