cubick84
cubick84

Reputation: 11

UI hangs until all fetches are done

I have this code to search through different tables, my problem is that I cannot interact with the UI until the las fetch request is executed. If I search for specific value and the result is in "Table2" the tableView updates fine but cannot interact with it until it finishes searching the last table. The func loadData() just takes a few milliseconds to execute and exit and the fetches are executing in a different thread. I don't know what's wrong with this code, any help or advice? The total amount of records in all tables is about 5 millions, it takes some time to search through all of them, that's why I don't want to keep the user waiting if some results are available before it finishes searching the entire db.

func loadData () {
    let tablas = ["Table1", "Table2", "Table3", "Table4", "Table5", "Table6", "Table7", "Table8", "Table9", "Table10", "Table11"]
    let managedContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
    managedContext.parentContext = self.moc
    for tbl in tablas {
        managedContext.performBlock {
            let fetchRequest = NSFetchRequest(entityName: tbl)
            let predicate = NSPredicate(format: "name CONTAINS %@", self.filter)
            fetchRequest.predicate = predicate
            fetchRequest.resultType = NSFetchRequestResultType.ManagedObjectIDResultType
            fetchRequest.fetchLimit =  50
            fetchRequest.fetchBatchSize = 10
            do {
                let results = try managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObjectID]
                if results.count != 0 {
                    self.resultArray.appendContentsOf(results)
                    dispatch_async(dispatch_get_main_queue()) {
                        self.tableView.reloadData()
                    }
                }
            } catch let error as NSError {
                dispatch_async(dispatch_get_main_queue()) {
                    let errorAlert = UIAlertController(title: "Error!!!", message: error.localizedDescription, preferredStyle: .Alert)
                    errorAlert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
                    self.presentViewController(errorAlert, animated: true, completion: nil)
                }
            }
        }
    }
}

Upvotes: 1

Views: 66

Answers (2)

DanielEdrisian
DanielEdrisian

Reputation: 726

The UI handles most of its process in the main thread. If you have a major process, don't run it on the main thread synchronously. You can run it asynchronously on the main thread.

The code to asynchronously run on main thread:

dispatch_async(dispatch_get_main_queue(), {

    // RUN CODE OVER HERE

})

Upvotes: 0

Related Questions