Background Thread Updates
Intermediate Training Core Data
In this lesson, we will learn how to update the UI after we create all of our Companies in core data by using DispatchQueue.main to get back on the main thread. Next we move onto updating our Company objects on a background thread which is much trickier. To perform this correctly, we are forced to reset our context on the main thread so that we can refetch everything. However, this is incredibly inefficient since we don't want to get everything again if we're just making a small set of changes. In the next lesson, we examine how we can set up relationships on our contexts so that we can merge changes automatically.

Comments (9)
magic
5 years ago
Wow! I can’t stop myself from continuing this series!! Great way of teaching thank u <3
Asaad Mirza
5 years ago
is it possible work peformebackgroundtask with nsfetchedresultscontroller ? and how i can do it, thanks in advance
Brian Voong
5 years ago
pawelcichonski
5 years ago
Is there any sense in performing background thread for DELETING OBJECTS? The reset button freezes but that's due to the animation, so I just stick with: self.companies.removeAll() self.tableView.reloadData() Then it works instantly. But would you implement delete in background or that's not necessary? Even if I try to delete them in background queue it gives: 'An NSManagedObjectContext cannot delete objects in other contexts', made an error somewhere: @objc private func handleReset() { CoreDataManager.shared.persistentContainer.performBackgroundTask { (backgroundContext) in self.companies.forEach { (company) in backgroundContext.delete(company) } let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: Company.fetchRequest()) do { try backgroundContext.execute(batchDeleteRequest) self.companies.removeAll() self.tableView.reloadData() } catch let deleteError { print("Failed to delete objects from Core Data", deleteError) } } }
Nicolas.Jochnick
5 years ago
Thanks so much Brian! The course is helping me stay sharp for my second year CS courses at UC Berkeley. Go Bears!
Brian Voong
5 years ago
jpickard
5 years ago
Hi Brian - Is this a good way to do a refresh from the front end? I'm new to all of this and concerned about general architecture. Seems to be stable when testing. Guessing that I could polish it up w/ some GCS time limits, w/ an alternate load new and delete old strategy vs delete then load. Note: this is w/in a FlowLayout controller class so I'm handling the refresh w/ a lazy var UIBarButtonItem. // Refresh data @objc func handleRefresh() { self.refreshBarButtonItem.isEnabled = false DispatchQueue.global(qos: .userInitiated).sync { Service.shared.deleteCompanies() Service.shared.downloadingCompaniesFromRemoteJSON() DispatchQueue.main.async { self.refreshBarButtonItem.isEnabled = true // Update the UI } } }
Brian Voong
5 years ago
Savoki
5 years ago
Hi Brian, I found that doWork() and doUpdate() have the same logic, why doWork() works while doUpdate() not? @objc private func doUpdates() { CoreDataManager.shared.persistentContainer.performBackgroundTask { (backgroundContext) in let request: NSFetchRequest<Company> = Company.fetchRequest() do { let companies = try backgroundContext.fetch(request) companies.forEach({ (company) in company.name = "B: \(company.name ?? "")" }) do { try backgroundContext.save() DispatchQueue.main.async { self.companies = CoreDataManager.shared.fetchCompanies() self.tableView.reloadData() } @objc private func doWork() { CoreDataManager.shared.persistentContainer.performBackgroundTask { (backgroundContext) in (0...20).forEach { (value) in let company = Company(context: backgroundContext) company.name = String(value) } do { try backgroundContext.save() DispatchQueue.main.async { self.companies = CoreDataManager.shared.fetchCompanies() self.tableView.reloadData() }
johnicode101
3 years ago
im having the same problem but he doesnt answer
jwaples
5 years ago
Would it be possible to add a tab bar controller to the bottom of this view controller with all the companies? this view controller is a table view so I'm not sure. Thank you for these videos - they are really instructive
iOS-Dev
4 years ago
Ofcourse, You can add tab bar controller inside the view controller. All the best!
Cinquain
4 years ago
Good stuff good stuff
romer_96p@hotmail.com
3 years ago
Everything works but im getting this bug on the console: [error] warning: 'Company' (0x60000102c8f0) from NSManagedObjectModel (0x60000043cd20) claims 'CoreDataLBTA.Company'. Haven't been able to find a viable solution... :/
romer_96p@hotmail.com
3 years ago
This bug persist in the Background thread... how to get it fixed?
romer_96p@hotmail.com
3 years ago
I fixed the issues if anyone has the same problem: The trouble is that I was loading the same NSManagedObjectModel more than once... using 'let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext' (by the way this only works for the main thread). I'd suggest you use the 'CoreDataManager.swift' file Brian has to access you context container before committing
HELP & SUPPORT