Skip to content

Instantly share code, notes, and snippets.

@bjhomer
Created October 5, 2012 20:25
Show Gist options
  • Save bjhomer/3842165 to your computer and use it in GitHub Desktop.
Save bjhomer/3842165 to your computer and use it in GitHub Desktop.
Core data asynchronous fetching API proposal
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface CDAsynchronousArray : NSArray
// Provides access to the full count of objects. May be slow, e.g. if the underlying data store
// is only providing paginated access to objects. May not even be available, as in a search
// engine result set.
- (void)accessCountWithHandler:(void (^)(NSUInteger count, NSError *))countHandler;
// These methods provide non-blocking access to potentially faulted objects.
- (void)accessObjectAtIndex:(NSUInteger)idx withHandler:(void (^)(NSManagedObject *, NSError *))objectHandler;
- (void)accessObjectsAtIndices:(NSIndexSet *)indices withHandler:(void (^)(NSArray *, NSError *))objectsHandler
// The objects this accesses are guaranteed to not be faults
- (void)accessAttributesOfObjectsAtIndices:(NSIndexSet *)indices withHandler:(void (^)(NSArray *, NSError *))objectsHandler;
// A some data stores may not be able to quickly give us full count,
// but rather only provide a "next page" link. This allows us to know
// when we've reached the end of the array. Probably returns the highest
// requested index + 1, if the final count is not known.
- (NSUInteger)indexOfLastKnownObject;
@end
@interface NSManagedObject (AsynchronousFetching)
- (void)accessAttributesWithHandler:(void (^)(NSError *))handler;
@end
@interface Foo : NSManagedObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) Bar *bar;
@property (nonatomic, retain) NSIncompleteArray *childFoos;
@end
@interface Bar : NSManagedObject
@end
static void example(void) {
NSManagedObjectContext *context;
NSFetchedRequest *fetchRequest;
NSError *error;
CDAsynchronousArray *array = [context executeFetchRequest:fetchRequest error:&error];
[array accessObjectAtIndex:0 withHandler:^(Foo *obj, NSError *error) {
// All handlers are called on the thread of the context
NSLog(@"Array fetched object count: %u", array.fetchedObjectCount);
demoProperties(obj);
}];
}
static void demoProperties(Foo *foo) {
[foo accessAttributesWithHandler:^ (NSError *error){
// This is guaranteed to not block.
foo.bar;
}];
// This is currently just an empty array. It doesn't even know
// how many objects are in it.
CDAsynchronousArray *children = foo.childFoos;
[children accessCountWithHandler:^(NSUInteger count, NSError *error) {
// Now it knows how many children it has.
NSLog(@"Children count: %u", count)
}];
[children accessObjectAtIndex:0 withHandler:^(Foo *foo, NSError *error) ] {
// Now I can access the child, but remember, it's still a fault.
// If I access foo.name directly, it may block.
[foo accessAttributesWithHandler:^(NSError *error) {
// In here, foo.name is guaranteed to be non-blocking.
NSLog(@"Foo name: %@", foo.name);
}]
}];
// The above nested blocks could be simplified as follows:
[children accessAttributesOfObjectsAtIndices:[NSIndexSet indexSetWithIndex:0] withHandler:
^(NSArray *objs, NSError *error) {
Foo *foo = objs[0];
// This will not block
NSLog(@"Foo name: %@", foo.name);
}]
}
@bjhomer
Copy link
Author

bjhomer commented Oct 5, 2012

This is a proposal for an asynchronous fetching and faulting API for Core Data. I've been wanting this for a while for use with an NSIncrementalStore backed by a web service. If this proposal is interesting to you, please do 2 things:

  1. Tell me how it could be improved.
  2. File a bug requesting asynchronous fetching for CoreData. (http://bugreporter.apple.com)

Seriously. File a bug. Please. Word is that at least some of the Core Data engineers would love to add asynchronous fetching to Core Data, but there has been very little interest expressed by developers, so other things get prioritized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment