UI freezes on executing NSBatchDeleteRequest

Viewed 357
NSFetchRequest *request = [Report fetchRequest];
request.predicate = [NSPredicate predicateWithFormat: @"reportId IN %@",self.selectedRowsInEditMode];

NSBatchDeleteRequest *deleteDetailsRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
deleteDetailsRequest.resultType = NSBatchDeleteResultTypeStatusOnly;
[self.managedObjectContext executeRequest:deleteDetailsRequest error:&errorExecuteRequest];

if (!errorExecuteRequest) {
    NSError *deleteSaveError;
    BOOL saveSuccessful = [self.managedObjectContext save:&deleteSaveError];
    [self.tableView removeLoadingActivityView];

This is the code where in I am trying to delete multiple report managed objects at once but when executeRequest is called the UI freezes for quite a while and then deletes. But NSBatchDeleteRequest is supposed to be very quick in terms of deletion. I tried multiple modifications to get it working but with no success. I am not sure what I am doing wrong here. So could anyone pls suggest to get it working without UI glitch.

2 Answers

Hope will helpful to you following code!!

I ended up adding the following to take care of the context after the batch delete.

[self.managedObjectContext refreshAllObjects];

// Initialize Fetch Request
NSFetchRequest *fetchRequest = [Report fetchRequest];

// Add Sort Descriptors
fetchRequest.predicate = [NSPredicate predicateWithFormat: @"reportId IN %@",self.selectedRowsInEditMode];

// Initialize Asynchronous Fetch Request
NSAsynchronousFetchRequest *asynchronousFetchRequest = [[NSAsynchronousFetchRequest alloc] initWithFetchRequest:fetchRequest completionBlock:^(NSAsynchronousFetchResult *result) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // Process Asynchronous Fetch Result
        [weakSelf processAsynchronousFetchResult:result];
    });
}];

// Execute Asynchronous Fetch Request
[self.managedObjectContext performBlock:^{
    // Execute Asynchronous Fetch Request
    NSError *asynchronousFetchRequestError = nil;
    NSAsynchronousFetchResult *asynchronousFetchResult = (NSAsynchronousFetchResult *)[weakSelf.managedObjectContext executeRequest:asynchronousFetchRequest error:&asynchronousFetchRequestError];

    if (asynchronousFetchRequestError) {
        NSLog(@"Unable to execute asynchronous fetch result.");
        NSLog(@"%@, %@", asynchronousFetchRequestError, asynchronousFetchRequestError.localizedDescription);
    }
}];

Or using below you use the global queue to run things in the background and the main queue to update the UI

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

You can create an Asynchronous Fetch Request, the synchronous can freeze the UI. This link Asynchronous Fetch Request is a tutorial in objective C that explain how.

Related