Skip to content

Commit

Permalink
Add TGRFetchedResultsTableViewController
Browse files Browse the repository at this point in the history
  • Loading branch information
gonzalezreal committed Apr 18, 2014
1 parent 31ff37b commit 4456f41
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 0 deletions.
6 changes: 6 additions & 0 deletions TGRDataSource.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
990C568A19017DAD00E382F1 /* NSObject+Abstract.m in Sources */ = {isa = PBXBuildFile; fileRef = 990C568919017DAD00E382F1 /* NSObject+Abstract.m */; };
990C568D19017EBA00E382F1 /* TGRArrayDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 990C568C19017EBA00E382F1 /* TGRArrayDataSource.m */; };
993DB7E71901990000653166 /* TGRFetchedResultsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 993DB7E61901990000653166 /* TGRFetchedResultsDataSource.m */; };
993DB7EA1901B86300653166 /* TGRFetchedResultsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 993DB7E91901B86300653166 /* TGRFetchedResultsTableViewController.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -60,6 +61,8 @@
990C568C19017EBA00E382F1 /* TGRArrayDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGRArrayDataSource.m; sourceTree = "<group>"; };
993DB7E51901990000653166 /* TGRFetchedResultsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGRFetchedResultsDataSource.h; sourceTree = "<group>"; };
993DB7E61901990000653166 /* TGRFetchedResultsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGRFetchedResultsDataSource.m; sourceTree = "<group>"; };
993DB7E81901B86300653166 /* TGRFetchedResultsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGRFetchedResultsTableViewController.h; sourceTree = "<group>"; };
993DB7E91901B86300653166 /* TGRFetchedResultsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGRFetchedResultsTableViewController.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -126,6 +129,8 @@
990C568C19017EBA00E382F1 /* TGRArrayDataSource.m */,
993DB7E51901990000653166 /* TGRFetchedResultsDataSource.h */,
993DB7E61901990000653166 /* TGRFetchedResultsDataSource.m */,
993DB7E81901B86300653166 /* TGRFetchedResultsTableViewController.h */,
993DB7E91901B86300653166 /* TGRFetchedResultsTableViewController.m */,
);
path = TGRDataSource;
sourceTree = "<group>";
Expand Down Expand Up @@ -239,6 +244,7 @@
buildActionMask = 2147483647;
files = (
990C568719017CB400E382F1 /* TGRDataSource.m in Sources */,
993DB7EA1901B86300653166 /* TGRFetchedResultsTableViewController.m in Sources */,
993DB7E71901990000653166 /* TGRFetchedResultsDataSource.m in Sources */,
990C568A19017DAD00E382F1 /* NSObject+Abstract.m in Sources */,
990C568D19017EBA00E382F1 /* TGRArrayDataSource.m in Sources */,
Expand Down
49 changes: 49 additions & 0 deletions TGRDataSource/TGRFetchedResultsTableViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// TGRFetchedResultsTableViewController.h
//
// Copyright (c) 2014 Guillermo Gonzalez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@class TGRFetchedResultsDataSource;

/**
`UITableViewController` subclass that takes its data from a `TGRFetchedResultsDataSource` object.
*/
@interface TGRFetchedResultsTableViewController : UITableViewController <NSFetchedResultsControllerDelegate>

/**
The data source used by this view controller.
*/
@property (strong, nonatomic) TGRFetchedResultsDataSource *dataSource;

/**
Maximum number of changes in the fetched results controller that will be animated. Default is 100.
*/
@property (nonatomic) NSUInteger contentAnimationMaximumChangeCount;

/**
Performs the fetch and reloads the table view.
This method is called everytime the `dataSource` property changes.
*/
- (void)performFetch;

@end
190 changes: 190 additions & 0 deletions TGRDataSource/TGRFetchedResultsTableViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// TGRFetchedResultsTableViewController.m
//
// Copyright (c) 2014 Guillermo Gonzalez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#import "TGRFetchedResultsTableViewController.h"
#import "TGRFetchedResultsDataSource.h"

@interface TGRFetchedResultsTableViewController ()

@property (strong, nonatomic) NSMutableIndexSet *insertedSections;
@property (strong, nonatomic) NSMutableIndexSet *deletedSections;
@property (strong, nonatomic) NSMutableArray *insertedRows;
@property (strong, nonatomic) NSMutableArray *deletedRows;
@property (strong, nonatomic) NSMutableArray *updatedRows;

@end

@implementation TGRFetchedResultsTableViewController

#pragma mark - Properties

- (void)setDataSource:(TGRFetchedResultsDataSource *)dataSource {
if (_dataSource != dataSource) {
_dataSource.fetchedResultsController.delegate = nil;
_dataSource = dataSource;
_dataSource.fetchedResultsController.delegate = self;

self.tableView.dataSource = dataSource;
[self performFetch];
}
}

#pragma mark - Lifecycle

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) {
_contentAnimationMaximumChangeCount = 100;
}

return self;
}

- (void)performFetch {
if (self.dataSource) {
NSError *error = nil;
[self.dataSource.fetchedResultsController performFetch:&error];
NSAssert(error == nil, @"%@ performFetch: %@", self, error);
}

[self.tableView reloadData];
}

#pragma mark - NSFetchedResultsControllerDelegate

- (void) controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type {
switch (type) {
case NSFetchedResultsChangeInsert:
[self.insertedSections addIndex:sectionIndex];
break;

case NSFetchedResultsChangeDelete:
[self.deletedSections addIndex:sectionIndex];
break;

default:
break;
}
}

- (void) controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
case NSFetchedResultsChangeInsert:
if (![self.insertedSections containsIndex:(NSUInteger)newIndexPath.section]) {
[self.insertedRows addObject:newIndexPath];
}
break;

case NSFetchedResultsChangeDelete:
if (![self.deletedSections containsIndex:(NSUInteger)indexPath.section]) {
[self.deletedRows addObject:indexPath];
}
break;

case NSFetchedResultsChangeUpdate:
[self.updatedRows addObject:indexPath];
break;

case NSFetchedResultsChangeMove:
if (![self.insertedSections containsIndex:(NSUInteger)newIndexPath.section]) {
[self.insertedRows addObject:newIndexPath];
}
if (![self.deletedSections containsIndex:(NSUInteger)indexPath.section]) {
[self.deletedRows addObject:indexPath];
}
break;
}
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSUInteger changeCount = self.insertedSections.count +
self.deletedSections.count +
self.insertedRows.count +
self.deletedRows.count +
self.updatedRows.count;

if (changeCount <= self.contentAnimationMaximumChangeCount) {
[self.tableView beginUpdates];
[self.tableView deleteSections:self.deletedSections withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView insertSections:self.insertedSections withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView deleteRowsAtIndexPaths:self.deletedRows withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView insertRowsAtIndexPaths:self.insertedRows withRowAnimation:UITableViewRowAnimationRight];
[self.tableView reloadRowsAtIndexPaths:self.updatedRows withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
else {
[self.tableView reloadData];
}

self.insertedSections = nil;
self.deletedSections = nil;
self.insertedRows = nil;
self.deletedRows = nil;
self.updatedRows = nil;
}

#pragma mark - Private

- (NSMutableIndexSet *)insertedSections {
if (!_insertedSections) {
_insertedSections = [[NSMutableIndexSet alloc] init];
}
return _insertedSections;
}

- (NSMutableIndexSet *)deletedSections {
if (!_deletedSections) {
_deletedSections = [[NSMutableIndexSet alloc] init];
}
return _deletedSections;
}

- (NSMutableArray *)insertedRows {
if (!_insertedRows) {
_insertedRows = [[NSMutableArray alloc] init];
}
return _insertedRows;
}

- (NSMutableArray *)deletedRows {
if (!_deletedRows) {
_deletedRows = [[NSMutableArray alloc] init];
}
return _deletedRows;
}

- (NSMutableArray *)updatedRows {
if (!_updatedRows) {
_updatedRows = [[NSMutableArray alloc] init];
}
return _updatedRows;
}

@end

0 comments on commit 4456f41

Please sign in to comment.