Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 53ad45a9259a23a6b81961c6aa4bc7d2841811a5 @indragie indragie committed Sep 24, 2011
Showing with 413 additions and 0 deletions.
  1. +12 −0 .gitignore
  2. +82 −0 README.md
  3. +69 −0 SNRFetchedResultsController.h
  4. +250 −0 SNRFetchedResultsController.m
@@ -0,0 +1,12 @@
+.DS_Store
+*.swp
+*~.nib
+
+build/
+
+*.pbxuser
+*.perspective
+*.perspectivev3
+*.mode1v3
+*.mode2v3
+*.xcuserdata
@@ -0,0 +1,82 @@
+## SNRFetchedResultsController: Automatic Core Data change tracking for OS X
+
+`SNRFetchedResultsController` is a "port" (not exactly) of `NSFetchedResultsController`` from iOS to OS X. It is not a drop in replacement for `NSFetchedResultsController`, but performs many of the same tasks in relation to managing results from a Core Data fetch and notifying a delegate when objects are inserted, deleted, updated, or moved in order to update the UI.
+
+## NSFetchedResultsController vs. SNRFetchedResultsController
+
+### Limitations
+
+- `SNRFetchedResultsController` does not support sections or caching, mainly because (unlike `UITableView``) `NSTableView`` does not support sections. That said, `SNRFetchedResultsController` can be used with custom UI controls that do support sectioning, so this would be a nice feature to add in the future.
+
+### Differences
+
+- As a result of having no section support, `SNRFetchedResultsController` uses indexes (`NSUInteger`) instead of `NSIndexPath`
+
+## ARC
+
+This project was written assuming that the code would be compiled under ARC. This means that there is no memory management code present, so if you are going to use this class in a non-ARC project then the correct retain/release calls will need to be inserted manually.
+
+## Example Usage
+
+### Creating a fetched results controller
+
+````
+NSFetchRequest *request = [[NSFetchRequest alloc] init];
+ request.entity = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:context];
+ request.sortDescriptors = [NSArray arrayWithObjects:[NSSortDescriptor sortDescriptorWithKey:@"year" ascending:YES], nil];
+ request.predicate = [NSPredicate predicateWithFormat:@"wheels.@count != 0"];
+ request.fetchBatchSize = 20;
+ self.fetchedResultsController = [[SNRFetchedResultsController alloc] initWithManagedObjectContext:context fetchRequest:request];
+ self.fetchedResultsController.delegate = self;
+ NSError *error = nil;
+ [self.fetchedResultsController performFetch:&error];
+ if (error) {
+ NSLog(@"Unresolved error: %@ %@", error, [error userInfo]);
+ }
+````
+
+### NSTableViewDataSource implementation
+
+````
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
+{
+ return [self.fetchedResultsController count];
+}
+- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
+{
+ return [self.fetchedResultsController objectAtIndex:rowIndex];
+}
+````
+
+### SNRFetchedResultsControllerDelegate implementation for NSTableView
+
+````
+- (void)controller:(SNRFetchedResultsController *)controller didChangeObject:(id)anObject atIndex:(NSUInteger)index forChangeType:(SNRFetchedResultsChangeType)type newIndex:(NSUInteger)newIndex
+{
+ switch (type) {
+ case SNRFetchedResultsChangeDelete:
+ [self.tableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:index] withAnimation:NSTableViewAnimationSlideLeft];
+ break;
+ case SNRFetchedResultsChangeInsert:
+ [self.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:newIndex] withAnimation:NSTableViewAnimationSlideDown];
+ break;
+ case SNRFetchedResultsChangeUpdate:
+ [self.tableView reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:index] columnIndexes:[NSIndexSet indexSetWithIndex:0]];
+ break;
+ case SNRFetchedResultsChangeMove:
+ [self.tableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:index] withAnimation:NSTableViewAnimationSlideLeft];
+ [self.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:newIndex] withAnimation:NSTableViewAnimationSlideDown];
+ break;
+ default:
+ break;
+ }
+}
+````
+
+## Who am I?
+
+I'm Indragie Karunaratne, a 17 year old Mac OS X and iOS Developer from Edmonton AB, Canada. Visit [my website](http://indragie.com) to check out my work, or to get in touch with me. ([follow me](http://twitter.com/indragie) on Twitter!)
+
+## Licensing
+
+`SNRFetchedResultsController` is licensed under the [BSD license](http://www.opensource.org/licenses/bsd-license.php).
@@ -0,0 +1,69 @@
+//
+// SNRFetchedResultsController.h
+// Sonora
+//
+// Created by Indragie Karunaratne on 11-07-11.
+// Copyright 2011 Indragie Karunaratne. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreData/CoreData.h>
+
+enum {
+ SNRFetchedResultsChangeInsert = 1,
+ SNRFetchedResultsChangeDelete = 2,
+ SNRFetchedResultsChangeMove = 3,
+ SNRFetchedResultsChangeUpdate = 4
+};
+typedef NSUInteger SNRFetchedResultsChangeType;
+
+@protocol SNRFetchedResultsControllerDelegate;
+@interface SNRFetchedResultsController : NSObject
+@property (nonatomic, assign) id<SNRFetchedResultsControllerDelegate> delegate;
+/** Objects fetched from the managed object context. -performFetch: must be called before accessing fetchedObjects, otherwise a nil array will be returned */
+@property (nonatomic, retain, readonly) NSArray *fetchedObjects;
+/** Managed object context and fetch request used to execute the fetch */
+@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
+@property (nonatomic, retain, readonly) NSFetchRequest *fetchRequest;
+/**
+ Creates a new SNRFetchedResultsController object with the specified managed object context and fetch request
+ @param context The managed object context
+ @param request The fetch request
+ */
+- (id)initWithManagedObjectContext:(NSManagedObjectContext*)context fetchRequest:(NSFetchRequest*)request;
+/**
+ Performs a fetch to populate the fetchedObjects array. Will immediately return NO if there is no fetchRequest
+ @param error A pointer to an NSError object that can be used to retrieve more detailed error information in the case of a failure
+ @return A BOOL indicating whether the fetch was successful
+ */
+- (BOOL)performFetch:(NSError**)error;
+
+/** These are just a few wrapper methods to allow easy access to the fetchedObjects array */
+- (id)objectAtIndex:(NSUInteger)index;
+- (NSArray*)objectsAtIndexes:(NSIndexSet*)indexes;
+- (NSUInteger)indexOfObject:(id)object;
+- (NSUInteger)count;
+@end
+
+@protocol SNRFetchedResultsControllerDelegate <NSObject>
+@optional
+/**
+ Called right before the controller is about to make one or more changes to the content array
+ @param controller The fetched results controller
+ */
+- (void)controllerWillChangeContent:(SNRFetchedResultsController*)controller;
+/**
+ Called right after the controller has made one or more changes to the content array
+ @param controller The fetched results controller
+ */
+- (void)controllerDidChangeContent:(SNRFetchedResultsController*)controller;
+/**
+ Called for each change that is made to the content array. This method will be called multiple times throughout the change processing.
+ @param controller The fetched results controller
+ @param anObject The object that was updated, deleted, inserted, or moved
+ @param index The original index of the object. If the object was inserted and did not exist previously, this will be NSNotFound
+ @param type The type of change (update, insert, delete, or move)
+ @param newIndex The new index of the object. If the object was deleted, the newIndex will be NSNotFound.
+ */
+- (void)controller:(SNRFetchedResultsController*)controller didChangeObject:(id)anObject atIndex:(NSUInteger)index forChangeType:(SNRFetchedResultsChangeType)type newIndex:(NSUInteger)newIndex;
+@end
Oops, something went wrong.

0 comments on commit 53ad45a

Please sign in to comment.