Inherits from NSObject
Conforms to NSFetchedResultsControllerDelegate
Declared in TLIndexPathController.h

Overview

TLIndexPathController is TLIndexPathTools' version of NSFetchedResultsController. It should not come as a surprise, then, that you must use this class if you want to integrate with Core Data.

Although it primarily exists for Core Data integration, TLIndexPathController works interchangeably with NSFetchRequest or plain ‘ol arrays of arbitrary data. Thus, if you choose to standardize your view controllers on TLIndexPathController, it is possible to have a common programming model across all of your table and collection views.

TLIndexPathController also makes a few nice improvements relative to NSFetchedResultsController:

  • Items do not need to be presorted by section. The data model handles organizing sections.
  • Changes to your fetch request are animated. So you can get animated sorting and filtering.
  • There is only one delegate method to implement (versus five for NSFetchedResultsController).

The basic template for using TLIndexPathController in a (table) view controller is as follows:

#import <UIKit/UIKit.h>
#import "TLIndexPathController.h"
@interface ViewController : UITableViewController TLIndexPathControllerDelegate
@end

#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) TLIndexPathController *indexPathController;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.indexPathController = [[TLIndexPathController alloc] init];
}

#pragma mark - UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return self.indexPathController.dataModel.numberOfSections;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.indexPathController.dataModel numberOfRowsInSection:section];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    id item = [self.indexPathController.dataModel itemAtIndexPath:indexPath];
    //configure cell using data item
    return cell;
}

#pragma mark - TLIndexPathControllerDelegate

- (void)controller:(TLIndexPathController *)controller didUpdateDataModel:(TLIndexPathUpdates *)updates
{
    [updates performBatchUpdatesOnTableView:self.tableView withRowAnimation:UITableViewRowAnimationFade];
}

@end

This template works with plain arrays or NSFetchRequests. With plain arrays, you simply set the dataModel property of the controller (or set the items property and get a default data model). With NSFetchRequests, you set the fetchRequest property and call performFetch:. From then on, the controller updates the data model interinally every time the fetch results change (using an internal instance of NSFetchedResultsController and responding to controllerDidChangeContent messages).

In either case, whether you explicitly set a data model or the controller converts a fetch result into a data model, the controller creates the TLIndexPathUpdates object for you and passes it to the delegate, giving you an opportunity to perform batch updates:

- (void)controller:(TLIndexPathController *)controller didUpdateDataModel:(TLIndexPathUpdates *)updates
{
    [updates performBatchUpdatesOnTableView:self.tableView withRowAnimation:UITableViewRowAnimationFade];
}

Properties

cacheName

The name of the file used by this classe’s internal NSFetchedResultsController to cache section information.

@property (strong, nonatomic) NSString *cacheName

Discussion

Unlike NSFetchedResultsController, this property is writeable. After changing the fetch request, performFetch: must be called to trigger updates.

Declared In

TLIndexPathController.h

coreDataFetchedObjects

Returns the underlying core data fetched objects without the application of in-memory filtering or sorting.

@property (strong, nonatomic, readonly) NSArray *coreDataFetchedObjects

Declared In

TLIndexPathController.h

dataModel

The data model representation of the items being tracked by the controller.

@property (strong, nonatomic) TLIndexPathDataModel *dataModel

Discussion

Setting this property causes the any changes to be propagated to the controller’s delegate. The type of items and configuration of the new data model need not necessarily be the same as the previous data model, provided that the controller’s delegate is prepared to handle the changes.

Declared In

TLIndexPathController.h

delegate

The controller’s delegate.

@property (weak, nonatomic) id<TLIndexPathControllerDelegate> delegate

Declared In

TLIndexPathController.h

fetchRequest

The controller’s fetch request.

@property (strong, nonatomic) NSFetchRequest *fetchRequest

Discussion

Unlike, NSFetchedResultsController, this property is writeable. After changing the fetch request, performFetch: must be called to trigger updates.

Declared In

TLIndexPathController.h

ignoreDataModelChanges

Determines whether data model changes are ignored.

@property (nonatomic) BOOL ignoreDataModelChanges

Discussion

This property can be set to YES to prevent calling the didUpdateDataModel delegate method when the data model changes. This can be useful if the view controller wants to reload the table without animation by calling reloadData, rather than having the batch updates performed.

Declared In

TLIndexPathController.h

ignoreFetchedResultsChanges

Determines whether incremental fetch request changes are ignored.

@property (nonatomic) BOOL ignoreFetchedResultsChanges

Discussion

This property can be set to YES to temporarily ignore incremental fetched results changes, such as when a table is in edit mode. This can also be useful for explicitly setting the data model and not having the changes overwritten by the fetch request.

Declared In

TLIndexPathController.h

inMemoryPredicate

The in-memory predicate.

@property (strong, nonatomic) NSPredicate *inMemoryPredicate

Discussion

This optional predicate will be evaluated in-memory against the underlying fetched result. If the controller is already fetched, it is not necessary to call performFetch: again after setting this property because the batch updates are processed immediately.

Declared In

TLIndexPathController.h

inMemorySortDescriptors

The in-memory sort descriptors.

@property (strong, nonatomic) NSArray *inMemorySortDescriptors

Discussion

These optional sort descriptors will be applied in-memory against the underlying fetched result. If the controller is already fetched, it is not necessary to call performFetch: again after setting this property because the batch updates are processed immediately.

Declared In

TLIndexPathController.h

isFetched

Returns YES if performFetch: has ever been called.

@property (nonatomic) BOOL isFetched

Discussion

This property does not indicate whether the fetched results are fresh or stale. For example, if the fetchRequest is modified after performFetch: has been called, the isFetched property will continue to return YES.

Declared In

TLIndexPathController.h

items

The items being tracked by the controller.

@property (strong, nonatomic) NSArray *items

Discussion

Setting this property causes a new data model to be created and any changes propagated to the controller’s delegate. This new data model preserves the configuration of the previous data model. The type of items need not necessarily be the same as the previous data model, provided they are consistent with the configuration, such as indetifierKeyPath. If the new data model requires a different configuration, set the dataModel property directly.

Declared In

TLIndexPathController.h

managedObjectContext

The managed object context in which the fetch request is performed.

@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext

Discussion

Unlike, NSFetchedResultsController, this property is writeable. After changing the fetch request, performFetch: must be called to trigger updates.

Declared In

TLIndexPathController.h

Class Methods

deleteCacheWithName:

+ (void)deleteCacheWithName:(NSString *)name

Instance Methods

initWithDataModel:

Returns an index path controller initialized with the given data model.

- (instancetype)initWithDataModel:(TLIndexPathDataModel *)dataModel

Parameters

dataModel

the data model

Return Value

the index path controller with the given data model representation

Declared In

TLIndexPathController.h

initWithFetchRequest:managedObjectContext:sectionNameKeyPath:identifierKeyPath:cacheName:

Returns an index path controller initialized with the given fetch request and configuration parameters.

- (instancetype)initWithFetchRequest:(NSFetchRequest *)fetchRequest managedObjectContext:(NSManagedObjectContext *)context sectionNameKeyPath:(NSString *)sectionNameKeyPath identifierKeyPath:(NSString *)identifierKeyPath cacheName:(NSString *)name

Return Value

the index path controller with a default data model representation of the given fetch request

Discussion

@param fetchRequest @param context @param sectionNameKeyPath @param identifierKeyPath @param cacheName

Declared In

TLIndexPathController.h

initWithItems:

Returns an index path controller initialized with the given items.

- (instancetype)initWithItems:(NSArray *)items

Parameters

items

the aray of items

Return Value

the index path controller with a default data model representation of the given items

A default data model is initialized with items where the properties identifierKeyPath, sectionNameKeyPath are all nil. If any of these are required, use initWithDataModel: instead.

Declared In

TLIndexPathController.h

performBatchUpdates:completion:

Allows for making multiple changes to the controller with only a single controller:didUpdateDataModel: delegate callback. For example, change the fetch request (and perform fetch), in-memory sort descriptors, and in-memory predicate as a single update.

- (void)performBatchUpdates:(void ( ^ ) ( void ))updates completion:(void ( ^ ) ( BOOL finished ))completion

Parameters

completion

a block to be executed after the batch updates are performed. Note that controller:didUpdateDataModel: is called before this block.

This method is not to be confused with table or collection view batch udpates. It is strickly for batch changes to this controller (which may result in batch updates happening to the table or collection view through the delegate method).

udpates

a block that makes changes to the controller

Declared In

TLIndexPathController.h

performFetch:

Calling this method executes the fetch request and causes a new data model to be created with the fetch result and any changes propagated to the controller’s delegate. Unlike NSFetchedResultsController, repeated calls to this method will continue to propagate batch changes. This makes it possible to modify the fetch request’s predicate and/or sort descriptors and have the new fetch result be propagated as batch changes.

- (BOOL)performFetch:(NSError *__autoreleasing *)error

Declared In

TLIndexPathController.h