diff --git a/MagicalRecord/MGPDelegateManager.h b/MagicalRecord/MGPDelegateManager.h new file mode 100644 index 0000000..78f2cd1 --- /dev/null +++ b/MagicalRecord/MGPDelegateManager.h @@ -0,0 +1,19 @@ +// +// MGPDelegateManager.h +// NSBrief +// +// Created by Saul Mora on 1/27/13. +// Copyright (c) 2013 Magical Panda Software. All rights reserved. +// + +#import + +@interface MGPDelegateManager : NSProxy + +@property (nonatomic, assign, readonly) BOOL justResponded; +@property (nonatomic, assign) BOOL logOnNoResponse; +@property (nonatomic, weak) id proxiedObject; + +-(id)init; + +@end diff --git a/MagicalRecord/MGPDelegateManager.m b/MagicalRecord/MGPDelegateManager.m new file mode 100644 index 0000000..6415c18 --- /dev/null +++ b/MagicalRecord/MGPDelegateManager.m @@ -0,0 +1,59 @@ +// +// MGPDelegateManager.m +// NSBrief +// +// Created by Saul Mora on 1/27/13. +// Copyright (c) 2013 Magical Panda Software. All rights reserved. +// + +#import "MGPDelegateManager.h" + +@interface MGPDelegateManager () + +@end + + +@implementation MGPDelegateManager + +-(id)init +{ + _proxiedObject=nil; + _justResponded=NO; + _logOnNoResponse=NO; + return self; +} + +-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector +{ + NSMethodSignature *sig = [[_proxiedObject class] instanceMethodSignatureForSelector:selector]; + if (sig == nil) + { + sig = [NSMethodSignature signatureWithObjCTypes:"@^v^c"]; + } + _justResponded = NO; + return sig; +} + +-(void)forwardInvocation:(NSInvocation*)invocation +{ + if (_proxiedObject==nil) + { + if(_logOnNoResponse) + { + NSLog(@"Warning: proxiedObject is nil! This is a debugging message!"); + } + return; + } + if ([_proxiedObject respondsToSelector:[invocation selector]]) + { + [invocation invokeWithTarget:_proxiedObject]; + _justResponded=YES; + } + else if(_logOnNoResponse) + { + NSLog(@"Object \"%@\" failed to respond to delegate message \"%@\"! This is a debugging message.", [[self proxiedObject] class], NSStringFromSelector([invocation selector])); + } + return; +} + +@end diff --git a/MagicalRecord/UI/MGPFetchedResultsTableViewController.h b/MagicalRecord/UI/MGPFetchedResultsTableViewController.h new file mode 100644 index 0000000..626c052 --- /dev/null +++ b/MagicalRecord/UI/MGPFetchedResultsTableViewController.h @@ -0,0 +1,24 @@ +// +// MGPTableViewController.h +// NSBrief +// +// Created by Saul Mora on 1/27/13. +// Copyright (c) 2013 Magical Panda Software. All rights reserved. +// + +#import + +@protocol MGPFetchedResultsTableViewControllerDelegate + +- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath usingResults:(NSFetchedResultsController *)results; +- (void) configureCell:(UITableViewCell *)cell forObject:(id)object atIndexPath:(NSIndexPath *)indexPath; + +@end + +@interface MGPFetchedResultsTableViewController : UIViewController + +@property (nonatomic, strong, readonly) UITableView *tableView; +@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; +@property (nonatomic, weak) id delegate; + +@end diff --git a/MagicalRecord/UI/MGPFetchedResultsTableViewController.m b/MagicalRecord/UI/MGPFetchedResultsTableViewController.m new file mode 100644 index 0000000..dc365a3 --- /dev/null +++ b/MagicalRecord/UI/MGPFetchedResultsTableViewController.m @@ -0,0 +1,226 @@ +// +// MGPTableViewController.m +// NSBrief +// +// Created by Saul Mora on 1/27/13. +// Copyright (c) 2013 Magical Panda Software. All rights reserved. +// + +#import "MGPFetchedResultsTableViewController.h" +#import "UITableViewCell+MGPAdditions.h" +#import "MGPDelegateManager.h" + + +@interface MGPFetchedResultsTableViewController () + +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, assign) UITableViewStyle style; +@property (nonatomic, strong) MGPDelegateManager *delegateManager; + + +- (NSFetchedResultsController *) fetchedResultsControllerForTableView:(UITableView *)tableView; +- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath usingResults:(NSFetchedResultsController *)results; + +@end + + +@implementation MGPFetchedResultsTableViewController + +- (id) init; +{ + return [self initWithStyle:UITableViewStylePlain]; +} + +- (id) initWithStyle:(UITableViewStyle)style; +{ + self = [super init]; + if (self) + { + _style = style; + _delegateManager = [[MGPDelegateManager alloc] init]; + } + return self; +} + +-(void)setDelegate:(id)delegate; +{ + self.delegateManager.proxiedObject = delegate; +} + +-(id)delegate; +{ + return self.delegateManager.proxiedObject; +} + +-(void)loadView; +{ + UIView *container = [[UIView alloc] initWithFrame:CGRectZero]; + UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:self.style]; + + tableView.autoresizingMask = + UIViewAutoresizingFlexibleBottomMargin | + UIViewAutoresizingFlexibleHeight | + UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleRightMargin | + UIViewAutoresizingFlexibleTopMargin | + UIViewAutoresizingFlexibleWidth; + + tableView.delegate = self; + tableView.dataSource = self; + + [container addSubview:tableView]; + + self.tableView = tableView; + self.view = container; +} + +-(void)viewWillLayoutSubviews; +{ + // [super viewWillLayoutSubviews]; + self.tableView.frame = self.view.bounds; +} + +- (void)viewDidAppear:(BOOL)animated; +{ + [super viewDidAppear:animated]; + [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated]; +} + +- (NSFetchedResultsController *) fetchedResultsControllerForTableView:(UITableView *)tableView; +{ + return self.fetchedResultsController; +} + +- (UITableView *) tableViewForResultsController:(NSFetchedResultsController *)controller; +{ + return controller == self.fetchedResultsController ? self.tableView : self.searchDisplayController.searchResultsTableView; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + NSInteger count = [[[self fetchedResultsControllerForTableView:tableView] sections] count]; + + return count; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + NSInteger numberOfRows = 0; + NSFetchedResultsController *fetchController = [self fetchedResultsControllerForTableView:tableView]; + NSArray *sections = [fetchController sections]; + if(sections.count > 0) + { + id sectionInfo = [sections objectAtIndex:section]; + numberOfRows = [sectionInfo numberOfObjects]; + } + + return numberOfRows; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSFetchedResultsController *results = [self fetchedResultsControllerForTableView:tableView]; + + Class tableCellClass = [self cellTypeForResults:results] ?: [UITableViewCell class]; + UITableViewCell *cell = [tableCellClass cellForTableView:tableView]; + [self configureCell:cell atIndexPath:indexPath usingResults:results]; + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; +{ + [self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath usingResults:[self fetchedResultsControllerForTableView:tableView]]; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; +{ + NSFetchedResultsController *results = [self fetchedResultsControllerForTableView:tableView]; + return [self tableView:tableView heightForRowAtIndexPath:indexPath usingResults:results]; +} + +-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; +{ + NSFetchedResultsController *results = [self fetchedResultsControllerForTableView:tableView]; + id sectionInfo = [[results sections] objectAtIndex:section]; + return [sectionInfo name]; +} + +- (Class) cellTypeForResults:(NSFetchedResultsController *)results; +{ + return [UITableViewCell class]; +} + +- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath usingResults:(NSFetchedResultsController *)results; +{ + [self.delegate configureCell:cell forObject:[results objectAtIndexPath:indexPath] atIndexPath:indexPath]; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath usingResults:(NSFetchedResultsController *)results; +{ + return tableView.rowHeight; +} + +- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller +{ + UITableView *tableView = [self tableViewForResultsController:controller]; + [tableView beginUpdates]; +} + +- (void)controller:(NSFetchedResultsController *)controller + didChangeSection:(id )sectionInfo + atIndex:(NSUInteger)sectionIndex + forChangeType:(NSFetchedResultsChangeType)type +{ + UITableView *tableView = [self tableViewForResultsController:controller]; + + switch(type) + { + case NSFetchedResultsChangeInsert: + [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeDelete: + [tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + break; + } +} + + +- (void)controller:(NSFetchedResultsController *)controller + didChangeObject:(id)anObject + atIndexPath:(NSIndexPath *)theIndexPath + forChangeType:(NSFetchedResultsChangeType)type + newIndexPath:(NSIndexPath *)newIndexPath +{ + UITableView *tableView = [self tableViewForResultsController:controller]; + + switch(type) + { + case NSFetchedResultsChangeInsert: + [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeDelete: + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:theIndexPath] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeUpdate: + [self configureCell:[tableView cellForRowAtIndexPath:theIndexPath] atIndexPath:theIndexPath usingResults:controller]; + break; + + case NSFetchedResultsChangeMove: + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:theIndexPath] withRowAnimation:UITableViewRowAnimationFade]; + [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; + break; + } +} + + +- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller +{ + UITableView *tableView = [self tableViewForResultsController:controller]; + [tableView endUpdates]; +} + +@end diff --git a/MagicalRecord/UI/UITableViewCell+MGPAdditions.h b/MagicalRecord/UI/UITableViewCell+MGPAdditions.h new file mode 100644 index 0000000..e26572d --- /dev/null +++ b/MagicalRecord/UI/UITableViewCell+MGPAdditions.h @@ -0,0 +1,16 @@ +// +// MGPTableViewCell.h +// NSBrief +// +// Created by Saul Mora on 1/27/13. +// Copyright (c) 2013 Magical Panda Software. All rights reserved. +// + +#import + +@interface UITableViewCell (MGPAdditions) + ++ (id) cellForTableView:(UITableView *)tableView; ++ (id) cellForTableView:(UITableView *)tableView usingNib:(UINib *)nib; + +@end diff --git a/MagicalRecord/UI/UITableViewCell+MGPAdditions.m b/MagicalRecord/UI/UITableViewCell+MGPAdditions.m new file mode 100644 index 0000000..60345fa --- /dev/null +++ b/MagicalRecord/UI/UITableViewCell+MGPAdditions.m @@ -0,0 +1,46 @@ +// +// MGPTableViewCell.m +// NSBrief +// +// Created by Saul Mora on 1/27/13. +// Copyright (c) 2013 Magical Panda Software. All rights reserved. +// + +#import "UITableViewCell+MGPAdditions.h" + +@implementation UITableViewCell (MGPAdditions) + + ++ (NSString *)cellIdentifier; +{ + return NSStringFromClass([self class]); +} + ++ (UINib *) nib; +{ + UINib *nib = [UINib nibWithNibName:[self cellIdentifier] bundle:[NSBundle mainBundle]]; + return nib; +} + ++ (id) cellForTableView:(UITableView *)tableView; +{ + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[self cellIdentifier]]; + if (cell == nil) + { + cell = [[self alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[self cellIdentifier]]; + } + return cell; +} + ++ (id) cellForTableView:(UITableView *)tableView usingNib:(UINib *)nib; +{ + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[self cellIdentifier]]; + if (cell == nil) + { + NSArray *views = [nib instantiateWithOwner:nil options:nil]; + cell = [views lastObject]; + } + return cell; +} + +@end