Karuppu MGR Karuppu MGR - 6 months ago 54
iOS Question

Optimising UITableview to process huge set of data

Im using core data to store and retrieve datas that Im fetching from web services.
Im displaying those datas in a table view.
Following is my

cellForRowAtIndexPath
method.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
StatutoryMappingCell * cell = [tableView dequeueReusableCellWithIdentifier:@"myCell"];
if (!cell)
{
[tableView registerNib:[UINib nibWithNibName:@"KnowledgeMainCell" bundle:nil] forCellReuseIdentifier:@"myCell"];
cell = [tableView dequeueReusableCellWithIdentifier:@"myCell"];
}
cell.statMapping.text = [self.items objectAtIndex:indexPath.row];

return cell;
}


self.items
contains the datas that has to be loaded in the
tableview
.

The problem that Im facing is,


  1. Im getting huge set of data from the server which is like 2000 records. So the
    tableview
    loading is getting very slow. How can I optimise the above code to handle such huge record?

  2. Is there any ways that I can do pagination in iOS where the user can click load more button at the bottom to retrieve more contents as in facebook?


Answer

@MGR, Using NsfetchedresultsController you can achieve it.

Here you can query the data from CD.

For Swift :

lazy var fetchedResultsController: NSFetchedResultsController = {
    // Initialize Fetch Request
    let fetchRequest = NSFetchRequest(entityName: "Item")

    // Add Sort Descriptors
    let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]

    // Here you can set the limit of Fetch Using FetchRequest property 

    // Initialize Fetched Results Controller
    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

    // Configure Fetched Results Controller
    fetchedResultsController.delegate = self

    return fetchedResultsController
}()

For Objective c:

create one property in .h file

@property (strong,nonatomic) NSFetchedResultsController *fetchedResultsController;

in .m implement this

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }


    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"EntityName" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setFetchBatchSize:20];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
    aFetchedResultsController.delegate = self;
    _fetchedResultsController = aFetchedResultsController;

    NSArray *result = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
    NSLog(@"Result: %@", result);

    NSError *error = nil;
    if (![_fetchedResultsController performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

When ever new data saved in coreData, it will automatically reflect in Tableview with the help of NFC delegate Metods.

// MARK: Fetched Results Controller Delegate Methods
func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}

// This will be called after all changes happened in cell.

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

// This will be called Every time whenever you delete or insert or moving the cell

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 {
            let cell = tableView.cellForRowAtIndexPath(indexPath) as! ToDoCell
            configureCell(cell, atIndexPath: indexPath)
        }
        break;
    case .Move:
        if let indexPath = indexPath {
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }

        if let newIndexPath = newIndexPath {
            tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade)
        }
        break;
    }
}

Thats it. Hope this will help you.

For reference follow this link.https://www.hackingwithswift.com/read/38/10/optimizing-core-data-performance-using-nsfetchedresultscontrolle