Skie
Skie

Reputation: 111

how to load the Core Data in background thread

i have some big data in my Core Data store how can i load this data in background thread?

    func connectionCoreData() {
        let fetchRequest = NSFetchRequest<PersonalClass>(entityName: "PersonalBase")
        let sortDescriptor = NSSortDescriptor(key: "personName", ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptor]
        if let managerObjectContext = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext {
            fetchResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managerObjectContext, sectionNameKeyPath: nil, cacheName: nil)
            fetchResultController.delegate = self
            do {
                try fetchResultController.performFetch()
                personalArray = fetchResultController.fetchedObjects!
                self.tableView.reloadData()
            } catch {
                print(error)
            }
        }
    }

i need add core data load in background thread and then update my tableView

Upvotes: 1

Views: 2007

Answers (1)

ELKA
ELKA

Reputation: 735

First, you should put in mind that a managedObjectContext runs on a single thread. And you should access/edit the loaded objects on the same thread.

In your case, you will interact with the objects that you are going to load on the main thread. For example, the loaded database objects will fill a tableView and this should be done on the main thread. This forces the managedObjectContext to be of MainContextType which runs on the main thread.

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html

You should not be afraid of running the NSFetchedResultsController on the main thread because it loads the objects in batches. However, you aren't using the FetchedResults Controller as it should. You shouldn't have these two lines in your code.

personalArray = fetchResultController.fetchedObjects!
self.tableView.reloadData()

You should access the loaded object using this method fetchResultController .objectAtIndexPath(indexPath).

This is an example of how to use the NSFetchedResultsController

class ViewController: UITableViewController NSFetchedResultsControllerDelegate{

    lazy var fetchedResultsController: NSFetchedResultsController = {
        let fetchRequest = ... //Create the fetch request
        let sortDescriptor = ... //Create a sortDescriptor
        let predicate = ...//Create the predicate if you want to filter the results
        fetchRequest.predicate = predicate

        let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: mainContext, sectionNameKeyPath: nil, cacheName: nil)
        fetchedResultsController.delegate = self
        return fetchedResultsController
    }()

    override fun viewDidLoad(){
         super.viewDidLoad()
         do {
             try self.fetchedResultsController.performFetch()
         }catch {
             print(error)
         }
    }

    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        tableView.beginUpdates()
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        tableView.endUpdates()
    }

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        switch (type) {
        case .Insert:
            if let indexPath = newIndexPath {
                tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            }
            break;
        case .Delete:
            if let indexPath = indexPath {
                tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            }
            break;
        case .Update:
            if let indexPath = indexPath {
                tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
            }
            break;
        case .Move:
            if let indexPath = indexPath, newIndexPath = newIndexPath {
                tableView.moveRowAtIndexPath(indexPath, toIndexPath: newIndexPath)
            }
            break;
        }
    }
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let sections = fetchedResultsController.sections {
            let sectionInfo = sections[section]
            return sectionInfo.numberOfObjects
        }
        return 0
    }

   override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
       let obj = fetchedResultsController.objectAtIndexPath(indexPath){
       ....
    }

}

Upvotes: 2

Related Questions