Core Data helper – REVISED

After my initial post regarding the the modified Core Data helper (by Björn Sållarp in this article) I decided to alter it to be a bit more helpful, so I added a few more methods to perform some commonly required tasks. You’ll find the revised class at the bottom of this article. Here are the new methods and examples of how you would use them. For completeness I’ve included the original methods too. The error checking for all the methods has been changed and should be working correctly (they don’t do anything – but you’ll be notified if something didn’t work and can write your own handling). So… after including the class in your file you can do the following…

Getting a data set from an entity (all records)

NSMutableArray *mutableFetchResults = [CoreDataHelper getObjectsForEntity:@"MyEntityName" withSortKey:@"mySortField" andSortAscending:NO andContext:managedObjectContext];

Getting a data set from an entity (filtered with predicate)

NSPredicate *tempPred = [NSPredicate predicateWithFormat:@"(myBoolValue == 0)"];
NSMutableArray *mutableFetchResults = [CoreDataHelper searchObjectsForEntity:@"MyEntityName" withPredicate:tempPred andSortKey:@"mySortField" andSortAscending:YES andContext:managedObjectContext];

Getting a record count for an entity (all records)

NSUInteger results = [CoreDataHelper countForEntity:@"MyEntityName" andContext:managedObjectContext];

Getting a record count for an entity (filtered with predicate)

NSPredicate *tempPred = [NSPredicate predicateWithFormat:@"(myBoolValue == 1)"];
NSUInteger results = [CoreDataHelper countForEntity:@"MyEntityName" withPredicate:tempPred andContext:managedObjectContext];

Deleting all records in an entity

BOOL results = [CoreDataHelper deleteAllObjectsForEntity:@"MyEntityName" andContext:managedObjectContext];

Okay, now you know what it does – here’s the class…

CoreDataHelper.h

#import 
#import 

@interface CoreDataHelper : NSObject {
}

+(NSMutableArray *)getObjectsForEntity:(NSString*)entityName withSortKey:(NSString*)sortKey andSortAscending:(BOOL)sortAscending andContext:(NSManagedObjectContext *)managedObjectContext;
+(NSMutableArray *)searchObjectsForEntity:(NSString*)entityName withPredicate:(NSPredicate *)predicate andSortKey:(NSString*)sortKey andSortAscending:(BOOL)sortAscending andContext:(NSManagedObjectContext *)managedObjectContext;
+(BOOL)deleteAllObjectsForEntity:(NSString*)entityName andContext:(NSManagedObjectContext *)managedObjectContext;
+(NSUInteger)countForEntity:(NSString *)entityName andContext:(NSManagedObjectContext *)managedObjectContext;
+(NSUInteger)countForEntity:(NSString *)entityName withPredicate:(NSPredicate *)predicate andContext:(NSManagedObjectContext *)managedObjectContext;

@end

CoreDataHelper.m

#import "CoreDataHelper.h"

@implementation CoreDataHelper

#pragma mark -
#pragma mark Retrieve objects

// Fetch objects with a predicate
+(NSMutableArray *)searchObjectsForEntity:(NSString*)entityName withPredicate:(NSPredicate *)predicate andSortKey:(NSString*)sortKey andSortAscending:(BOOL)sortAscending andContext:(NSManagedObjectContext *)managedObjectContext
{
	// Create fetch request
	NSFetchRequest *request = [[NSFetchRequest alloc] init];
	NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
	[request setEntity:entity];	
	
	// If a predicate was specified then use it in the request
	if (predicate != nil)
		[request setPredicate:predicate];
	
	// If a sort key was passed then use it in the request
	if (sortKey != nil) {
		NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
		NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
		[request setSortDescriptors:sortDescriptors];
		[sortDescriptors release];
		[sortDescriptor release];
	}
	
	// Execute the fetch request
	NSError *error = nil;
	NSMutableArray *mutableFetchResults = [[[managedObjectContext executeFetchRequest:request error:&error] mutableCopy] autorelease];
	[request release];
	
	// If the returned array was nil then there was an error
	if (mutableFetchResults == nil)
		NSLog(@"Couldn't get objects for entity %@", entityName);
	
	// Return the results
	return mutableFetchResults;
}

// Fetch objects without a predicate
+(NSMutableArray *)getObjectsForEntity:(NSString*)entityName withSortKey:(NSString*)sortKey andSortAscending:(BOOL)sortAscending andContext:(NSManagedObjectContext *)managedObjectContext
{
	return [self searchObjectsForEntity:entityName withPredicate:nil andSortKey:sortKey andSortAscending:sortAscending andContext:managedObjectContext];
}

#pragma mark -
#pragma mark Count objects

// Get a count for an entity with a predicate
+(NSUInteger)countForEntity:(NSString *)entityName withPredicate:(NSPredicate *)predicate andContext:(NSManagedObjectContext *)managedObjectContext
{
	// Create fetch request
	NSFetchRequest *request = [[NSFetchRequest alloc] init];
	NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
	[request setEntity:entity];
	[request setIncludesPropertyValues:NO];
	
	// If a predicate was specified then use it in the request
	if (predicate != nil)
		[request setPredicate:predicate];
	
	// Execute the count request
	NSError *error = nil;
	NSUInteger count = [managedObjectContext countForFetchRequest:request error:&error];
	[request release];
	
	// If the count returned NSNotFound there was an error
	if (count == NSNotFound)
		NSLog(@"Couldn't get count for entity %@", entityName);
	
	// Return the results
	return count;
}

// Get a count for an entity without a predicate
+(NSUInteger)countForEntity:(NSString *)entityName andContext:(NSManagedObjectContext *)managedObjectContext
{
	return [self countForEntity:entityName withPredicate:nil andContext:managedObjectContext];
}

#pragma mark -
#pragma mark Delete Objects

// Delete all objects for a given entity
+(BOOL)deleteAllObjectsForEntity:(NSString*)entityName andContext:(NSManagedObjectContext *)managedObjectContext
{
	// Create fetch request
	NSFetchRequest *request = [[NSFetchRequest alloc] init];
	NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext];
	[request setEntity:entity];	

	// Ignore property values for maximum performance
	[request setIncludesPropertyValues:NO];
	
	// Execute the count request
	NSError *error = nil;
	NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
	[request release];
	
	// Delete the objects returned if the results weren't nil
	if (fetchResults != nil) {
		for (NSManagedObject *manObj in fetchResults) {
			[managedObjectContext deleteObject:manObj];
		}
	} else {
		NSLog(@"Couldn't delete objects for entity %@", entityName);
		return NO;
	}
	
	return YES;	
}

@end

That’s all of it! I’m using this class in most of my applications to keep things tidy – and it works perfectly back to iOS 3.0.x. If it helps you, please post and let me know. By the way, I’ve commented it all so you can follow it through and see how it works.

Have a happy Christmas!
Simon

Leave a Reply