Created
December 23, 2016 18:35
-
-
Save DaveBatton/47376cdb3217fe7c37ad15352894f862 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MCFetchedResultsViewController.m | |
// MoneyCarta | |
// | |
// Created by Dave Batton on 5/5/15. | |
// Copyright (c) 2015 Project Black. All rights reserved. | |
// | |
#import "MCFetchedResultsViewController.h" | |
#import "AppDelegate.h" | |
#import "UIAlertView+MCAdditions.h" | |
#import "MCHeaderView.h" | |
@interface MCFetchedResultsViewController () | |
@property (nonatomic) BOOL hasDoneFirstFetch; | |
@end | |
@implementation MCFetchedResultsViewController | |
#pragma mark - Setup & Teardown | |
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil | |
{ | |
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; | |
if (self) { | |
_fetchedResultsManagedObjectContext = APPDELEGATE.managedObjectContext; | |
} | |
return self; | |
} | |
- (instancetype)initWithCoder:(NSCoder *)aDecoder | |
{ | |
self = [super initWithCoder:aDecoder]; | |
if (self) { | |
_fetchedResultsManagedObjectContext = APPDELEGATE.managedObjectContext; | |
} | |
return self; | |
} | |
- (void)dealloc | |
{ | |
_fetchedResultsController.delegate = nil; | |
_fetchedResultsController = nil; | |
_tableView.delegate = nil; | |
_tableView.dataSource = nil; | |
} | |
#pragma mark - UIViewController | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
[self.tableView registerClass:[MCHeaderView class] forHeaderFooterViewReuseIdentifier:@"MCHeaderView"]; | |
self.hasDoneFirstFetch = NO; | |
} | |
- (void)viewWillAppear:(BOOL)animated | |
{ | |
[super viewWillAppear:animated]; | |
if (self.hasDoneFirstFetch == NO) { | |
[self performFetch]; | |
} | |
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated]; | |
} | |
#pragma mark - Public | |
- (void)performFetch | |
{ | |
[UIAlertView mcShowAssert:([self.fetchedResultsEntityName length] > 0) message:@"MCFetchedResultsViewController requires a fetchedResultsEntityName."]; | |
[UIAlertView mcShowAssert:(self.fetchedResultsSortDescriptors.count > 0) message:@"MCFetchedResultsViewController requires fetchedResultsSortDescriptors."]; | |
NSError *error; | |
[self.fetchedResultsController performFetch:&error]; | |
[UIAlertView mcShowError:error]; | |
[self.tableView reloadData]; | |
self.hasDoneFirstFetch = YES; | |
} | |
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath | |
{ | |
// For subclasses to override. No need to call super. | |
} | |
- (NSIndexPath *)mapIndexPathFromFetchResultsController:(NSIndexPath *)indexPath | |
{ | |
return indexPath; | |
} | |
- (NSIndexPath *)mapIndexPathToFetchResultsController:(NSIndexPath *)indexPath | |
{ | |
return indexPath; | |
} | |
- (NSInteger)mapSectionFromFetchResultsController:(NSInteger)section | |
{ | |
return section; | |
} | |
- (NSInteger)mapSectionToFetchResultsController:(NSInteger)section | |
{ | |
return section; | |
} | |
#pragma mark - UITableViewDataSource | |
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView | |
{ | |
return self.fetchedResultsController.sections.count; | |
} | |
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section | |
{ | |
id<NSFetchedResultsSectionInfo> sectionInfo = self.fetchedResultsController.sections[section]; | |
return sectionInfo.name; | |
} | |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section | |
{ | |
id<NSFetchedResultsSectionInfo> sectionInfo = self.fetchedResultsController.sections[section]; | |
return sectionInfo.numberOfObjects; | |
} | |
#pragma mark - UITableViewDelegate | |
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section | |
{ | |
return [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:@"MCHeaderView"]; | |
} | |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
// Subclass should override. No need to call super. | |
return [[UITableViewCell alloc] init]; | |
} | |
#pragma mark - NSFetchedResultsControllerDelegate | |
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller | |
{ | |
[self.tableView beginUpdates]; | |
} | |
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type | |
{ | |
switch(type) { | |
case NSFetchedResultsChangeInsert: | |
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeDelete: | |
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
default: | |
break; | |
} | |
} | |
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath | |
{ | |
switch(type) { | |
case NSFetchedResultsChangeInsert: | |
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeDelete: | |
[self.tableView deleteRowsAtIndexPaths:@[indexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeUpdate: | |
[self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; | |
break; | |
case NSFetchedResultsChangeMove: | |
[self.tableView deleteRowsAtIndexPaths:@[indexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
} | |
} | |
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller | |
{ | |
[self.tableView endUpdates]; | |
} | |
#pragma mark - Accessors | |
- (void)setFetchedResultsEntityName:(NSString *)entityName | |
{ | |
[UIAlertView mcShowAssert:(_fetchedResultsController == nil) message:@"You must set fetchedResultsEntityName before the fetchedResultsController has been created."]; | |
_fetchedResultsEntityName = entityName; | |
} | |
- (void)setFetchedResultsPredicate:(NSPredicate *)predicate | |
{ | |
[UIAlertView mcShowAssert:(_fetchedResultsController == nil) message:@"You must set fetchedResultsPredicate before the fetchedResultsController has been created. After that, access its fetchRequest property directly."]; | |
_fetchedResultsPredicate = predicate; | |
} | |
- (void)setFetchedResultsSortDescriptors:(NSArray *)sortDescriptors | |
{ | |
[UIAlertView mcShowAssert:(_fetchedResultsController == nil) message:@"You must set fetchedResultsSortDescriptors before the fetchedResultsController has been created. After that, access its fetchRequest property directly."]; | |
_fetchedResultsSortDescriptors = sortDescriptors; | |
} | |
- (void)setFetchedResultsSectionNameKeyPath:(NSString *)keyPath | |
{ | |
[UIAlertView mcShowAssert:(_fetchedResultsController == nil) message:@"You must set fetchedResultsSectionNameKeyPath before the fetchedResultsController has been created."]; | |
_fetchedResultsSectionNameKeyPath = keyPath; | |
} | |
- (NSFetchedResultsController *)fetchedResultsController | |
{ | |
if (_fetchedResultsController != nil) { | |
return _fetchedResultsController; | |
} | |
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:self.fetchedResultsEntityName]; | |
fetchRequest.predicate = self.fetchedResultsPredicate; | |
fetchRequest.sortDescriptors = self.fetchedResultsSortDescriptors; | |
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest | |
managedObjectContext:self.fetchedResultsManagedObjectContext | |
sectionNameKeyPath:self.fetchedResultsSectionNameKeyPath | |
cacheName:nil]; | |
_fetchedResultsController.delegate = self; | |
return _fetchedResultsController; | |
} | |
- (void)setFetchedResultsManagedObjectContext:(NSManagedObjectContext *)context | |
{ | |
if (_fetchedResultsManagedObjectContext != context) { | |
[UIAlertView mcShowAssert:(_fetchedResultsController == nil) message:@"You can't change the managed object context after creating the fetched results controller."]; | |
_fetchedResultsManagedObjectContext = context; | |
} | |
} | |
#pragma mark - Actions | |
- (IBAction)toggleEdit:(id)sender | |
{ | |
[self.view endEditing:YES]; | |
if (self.tableView.isEditing) { | |
[APPDELEGATE saveTemporaryContext:self.fetchedResultsController.managedObjectContext]; | |
} | |
UIBarButtonSystemItem systemItem = self.tableView.isEditing ? UIBarButtonSystemItemEdit : UIBarButtonSystemItemDone; | |
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:systemItem | |
target:self | |
action:@selector(toggleEdit:)]; | |
[self.tableView setEditing:!self.tableView.isEditing animated:YES]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment