Using ActiveRecord to work with Core Data
Introduction
Active Record is a design pattern for applications that use a database to store information. The database table is displayed as an application class, and the display of the class object is a table row. The interface of such an object should contain functions such as Insert, Update, and Delete, plus properties that correspond to the columns of the table. When creating an object, a new row is added to the table, when the object is updated, the corresponding row in the table is also updated.
Core Data and Active Record
Core Data is based on the Active Record pattern, but you have to write rather cumbersome code to work with the database. For example, here is an example of Apple :
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
As you can see from the example, to search the Employee database for which the last name contains “Worsley” and salaries above the minimum salary, you have to write a lot of “extra” code.
Magical Panda provided a solution to this problem in their ActiveRecord for Core Data library.
Here is the same example, only using ActiveRecord for Core Data:
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary];
NSArray *employees = [Employee findAllSortedBy:@"firstName" asceding:YES withPredicate:predicate];
ActiveRecord for Core Data allows you to:
1. Make code cleaner for working with Core Data
2. It allows you to make simple single-line queries
3. Despite its simplicity, it allows you to modify NSFetchRequest when the request needs to be modified.
Using ActiveRecord for Core Data
Customization
Download the ActiveRecord for Core Data library and add it to the project:

Add to MyProjectName-Prefix.pch
#import "CoreData+ActiveRecordFetching.h"
in AppDelegate in application: didFinishLaunchingWithOptions: add a call
[ActiveRecordHelpers setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"MyProject.sqlite"];
This method creates an NSPersistentStore with the specified name and model file .xcdatamodeld that it finds in the bundle of the application.
Default Managed Object Context
When working with Core Data, the NSManagedObjectContext object is used. ActiveRecord for Core Data allows you to set DefaultContext, which will be NSManagedObjectContext by default for the entire application. Creating an NSManagedObjectContext for use in other threads is as follows:
NSManagedObjectContext *myNewContext = [NSManagedObjectContext newContext];
This context can be made by default, and then it will be used in all requests if the name of the request method does not end with "inContext:". It is recommended that you create and set the default context only in the main thread.
Data sampling
Suppose there is a Song class with id, length and name fields: The ActiveRecord for Core Data library contains the category "NSManagedObject + ActiveRecord.h", that is, all NSManagedObject descendants will reply to ActiveRecord for Core Data messages. Most methods in ActiveRecord for Core Data return an array of results. For example, if you need to find all Song objects in the database, the call will look like this: Search for songs sorted by name will look like: If there is a song with a unique attribute value, you can use the function: Also ActiveRecord for Core Data allows you to use NSPredicate : NSPredicate * songFilter = [NSPredicate predicateWithFormat: @ "length>% @", ...];
@interface Song : NSManagedObject
@property (nonatomic, retain) NSNumber * length;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * id;
@end
#import "Song.h"
@implementation Song
@dynamic length;
@dynamic name;
@dynamic id;
@end
NSArray *songs = [Song findAll];
NSArray *songsSorted = [Song findAllSortedByProperty:@"name" ascending:YES];
Song *song = [Song findFirstByAttribute:@"name" withValue:@"Imagine"];
NSArray *songs = [Song findAllWithPredicate:peopleFilter];
Data editing
Creating a record in the database using ActiveRecord for Core Data is very simple:
Song *song = [Song createEntity];
Deleting:
[song deleteEntity];
Editing attributes: After editing the data, you need to save the context:
Song *song = [Song createEntity];
song.name = "stairway to heaven";
song.length = [NSNumber numberWithInt:150];
[[NSManagedObjectContext defaultContext] save];