I'm using Xcode 9 and Swift 4. I start a download of multiple JSON files when the application is in the foreground. The application then parses these files and saves them to CoreData. This works well when the application is in the foreground. However, if the application is in the background, the files still download correctly, but the data is not parsed and saved to CoreData. It's only when the user returns to the foreground that the parsing and saving of data continues.
I have Background Modes turned on - Background Fetch and Remote notifications.
I have around 10 functions that are similar to the one below in which it processes the JSON files concurrently:
func populateStuff(json: JSONDictionary) -> Void {
let results = json["result"] as! JSONDictionary
let stuffData = results["Stuff"] as! [JSONDictionary]
let persistentContainer = getPersistentContainer()
persistentContainer.performBackgroundTask { (context) in
for stuff in stuffData {
let newStuff = Stuff(context: context)
newStuff.stuffCode = stuff["Code"] as? String
newStuff.stuffDescription = stuff["Description"] as? String
do {
try context.save()
} catch {
fatalError("Failure to save context: \(error)")
}
}
}
}
func getPersistentContainer() -> NSPersistentContainer {
let persistentContainer = NSPersistentContainer(name: "MyProjectName")
persistentContainer.loadPersistentStores { (_, error) in
if let error = error {
fatalError("Failed to load core data stack: \(error.localizedDescription)")
}
}
persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
persistentContainer.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
return persistentContainer
}
Can anyone advise me on why this might happen and how to over come this?
TIA
Use the beginBackgroundTaskWithName:expirationHandler:
method:
func populateStuff(json: JSONDictionary) -> Void {
// Perform the task on a background queue.
DispatchQueue.global().async {
// Request the task assertion and save the ID.
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks") {
// End the task if time expires.
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
self.backgroundTaskID = UIBackgroundTaskInvalid
}
// Parse the json files
let results = json["result"] as! JSONDictionary
let stuffData = results["Stuff"] as! [JSONDictionary]
let persistentContainer = getPersistentContainer()
persistentContainer.performBackgroundTask { (context) in
for stuff in stuffData {
let newStuff = Stuff(context: context)
newStuff.stuffCode = stuff["Code"] as? String
newStuff.stuffDescription = stuff["Description"] as? String
do {
try context.save()
} catch {
fatalError("Failure to save context: \(error)")
}
}
}
// End the task assertion.
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
self.backgroundTaskID = UIBackgroundTaskInvalid
}
Calling this method gives you extra time to perform important tasks. Notice the use of endBackgroundTask:
method right after the task is done. It lets the system know that you are done. If you do not end your tasks in a timely manner, the system terminates your app.
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