Maybe someone has experience of work with big Core Data bases (i have 32k of rows in my base, and i need to show all this base to the user and make some search in it) and when i'll try to read the base in to my fetchedResultsController i have 3-5 seconds delay, how i can fix this? Can i read this base in some background thread? or if i make separate my base on some parts via relations is it help? i try to load my base in viewDidAppear
override func viewDidAppear(_ animated: Bool) {
DispatchQueue.main.async {
self.connectFetchedRequest()
self.tableView.reloadData()
self.indicatorLoad.stopAnimating()
}
}
func connectFetchedRequest() {
do {
try self.fetchedResultsController.performFetch()
}catch {
print(error)
}
}
for search in the base i use UISearchBarDelegate method (but i still have some "lags" when add characters to the searchText)
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
block?.cancel()
block = DispatchWorkItem {
let predicate = NSPredicate(format: "cardName contains[c] %@", searchText)
self.fetchedResultsController.fetchRequest.predicate = predicate
self.connectFetchedRequest()
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.5, execute: block!)
}
i created fetchedResultsController with the following code
lazy var context: NSManagedObjectContext = {
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
return appDelegate!.managedObjectContext
}()
lazy var fetchedResultsController: NSFetchedResultsController<CardsBaseClass> = {
let fetchRequest = NSFetchRequest<CardsBaseClass>(entityName: "CardsBase")
let sortDescriptor = NSSortDescriptor(key: "cardName", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 50
fetchRequest.returnsObjectsAsFaults = false
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.context, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController.delegate = self
return fetchedResultsController
}()
for add new predicates from other viewController (which i open .overFullScreen so my main view with base is open too) i use the following code
predicateArrayClass.addPredicate(predicate: predicateType)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateTableViewByNewPredicate"), object: nil, userInfo: nil)
self.dismiss(animated: true, completion: nil)
where i called the update fetchResultController func
func updateTableViewByNewPredicate() {
searchController.searchBar.text! = ""
let predicateArray = predicateArrayClass.arrayOfPredicates
block = DispatchWorkItem {
self.fetchedResultsController.fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicateArray)
self.connectFetchedRequest()
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
DispatchQueue.global(qos: .background).async(execute: block!)
}
Here's some guidelines:
fetchBatchSize
of your fetch request to something like 50
, and returnsObjectsAsFaults
to NO
.estimatedRowHeight
or -tableView:estimatedHeightForRowAtIndexPath:
of UITableViewDelegate
will do.This will prevent loading all of the 32K records in memory on each reload.