Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / iPhone

CoreData Persistence Framework

5.00/5 (1 vote)
16 Mar 2012BSD3 min read 31K   800  
Ligth object wrapper for iOS CoreData.

Introduction

CoreData Persistence library has has been implemented for simplifying and to make it easier to work with the Core Data Framework and represents a light object wrapper. The project is inspired by the kbucek Persistence API framework built on Java. 

Background 

It is designed for common usage scenarios including Core Data stack handling and basic object (graph of objects) querying or possible use of projections for some attributes of managed objects.

It covers the base Core Data Framework functionality by using these common patterns: DAO (Data Access Object) and Factory.

Using the code

The library has a group of classes which act as light objects wrapped around the Cocoa predicates. In the following section are described the base blocks of the Persistence API.

At the very beginning, you need to set the store data file path and its store type inside of the app delegate right next to the calling of the method applicationDidFinishLaunching (for instance, for SQLite store type):

Objective-C
- (void)applicationDidFinishLaunching:(UIApplication *)application {  
    [DAOFactory setStorePath:@"test.sqlite"]; 
    [DAOFactory setStoreType:NSSQLiteStoreType];
    ... 

The file test.sqlite is empty or is a prefilled database file located inside the Resources group (Xcode). The file will by automatically copied for the first time into the Documents folder of the application.

DAOFactory

It is used for dynamic DAO creation of RuntimeDAO objects or descendants of the DAOBase class:

Objective-C
DAOFactory *factory = [DAOFactory factory];
DAO *dao = [factory createRuntimeDAO:@"EntityName"];

You can extend DAOFactory and implement factory methods for your custom DAOs:

Objective-C
DAOFactory *factory = [DAOFactory factory];
MyCustomDAO *dao = (MyCustomDAO*)[factory newDAO:MyCustomDAO.class];
...
[dao release];

DAO

The DAO class with its protocol defines generic methods for managed object manipulation. Each DAO serves for only one single managed object type, which means that it is defined for only this particular managed object type. The RuntimeDAO class is a simple DAO implementation which can be used if you do not need to implement custom methods for data object manipulation.

If you need or want to wrap up your business logic which is related to core data's object manipulation (CRUD with extended features), we recommend you implement it in your custom DAO.

Here is an example of DAO's methods declaration:

Objective-C
// returns all managed objects id
-(NSArray*)findAllId;

// returns all managed objects
-(NSArray*)findAll;

// returns all managed objects - with pagination
-(NSArray*)findAll:(NSUInteger)fetchOffset limit:(NSUInteger)limit;

// returns all managed objects id - with pagination
-(NSArray*)findAllId:(CDSearchCriteria*)criteria;

// returns all managed objects based on given criteria
-(NSArray*)findAll:(CDSearchCriteria*)criteria;

// returns all managed objects based on given criteria - with pagination
-(NSArray*)findAll:(CDSearchCriteria*)criteria 
  fetchOffset:(NSUInteger)fetchOffset limit:(NSUInteger)limit;

// returns all managed objects count
-(NSUInteger)count;

// returns all managed objects based on given criteria
-(NSUInteger)count:(CDSearchCriteria*)criteria;

// inserts new managed object and returns it to caller
-(NSManagedObject*)insertNewObject;

// deletes given managed object
-(void)deleteObject:(NSManagedObject*)object;

// resturns managed object with given id
-(NSManagedObject*)findObjectById:(NSManagedObjectID*)objectID;

// if flag is YES, merges an object with the state
// of the object available in the persistent store coordinator; 
// if flag is NO, simply refaults an object without merging (which also causes other
// related managed objects to be released, so you can use this method
// to trim the portion of your object graph you want to hold in memory) 
- (void)refreshObject:(NSManagedObject *)object mergeChanges:(BOOL)flag; 

Cocoa predicates - querying

The base class for managed objects querying serves the CDSearchCriteria class, which is simply the holder for 'filters', 'orders', and 'projections'. All of the classes appropriate to the criteria contain factory methods for the instantiation of the required criteria objects.

Filters

Filters are used as predicates for the restriction of query results.

Filters are represented by the CDFilter class (and its subclasses). None of the Core Data predicates (such as 'beginswith', 'ANY', 'ALL' operators… ) are not supported in this version.

Objective-C
CDSearchCriteria *criteria = [CDSearchCriteria criteria];
[criteria addFilter:[CDFilter like:@"stringProperty1" value:@"abc*" caseSensitive:NO]];
[criteria addFilter:[CDFilter isNotNull:@"timeStamp"]]; 

Orders

Orders are used to order query results. An order is represented by the CDOrder class, which is quite simple.

Objective-C
CDSearchCriteria *criteria = [CDSearchCriteria criteria];
[criteria addOrder:[CDOrder ascendingOrder:@"timeStamp"]];

Projections

Projections are used for obtaining not the whole graphs of managed objects but only attributes or the calculated values. Projections are represented by the CDProjection class.

Objective-C
CDSearchCriteria *criteria = [CDSearchCriteria criteria];
[criteria addProjection:[CDProjection createWithProperty:@"timeStamp"]];

After successful querying, the projection result values are stored in the array for each result row in the dictionary. Simple values of projection results are stored in the dictionary under the key of the property name.

Projection for a function is stored in the dictionary with a compound key in the following form:

Objective-C
@"function name:property name"

For example:

Objective-C
@"min:property1"

Functions

Functions are used in filters or projections and represent certain transformations of the managed object property values. In the current version, these are 'min', 'max', 'sum', and 'lower'.

Objective-C
CDSearchCriteria *criteria = [CDSearchCriteria criteria];
[criteria addFilter:[CDFilter isNotNull:@"timeStamp"]];
[criteria addProjection:[CDProjection createWithFunction:[CDFunction 
       sum:@"doubleValueProperty" resultType:NSDateAttributeType]]];

NSFetchedResultsController

The DAO protocol contains methods for easy creation of NSFetchedResultsController on the basis of the given criteria:

Objective-C
CDSearchCriteria *criteria = [CDSearchCriteria criteria];
...
DAO *dao = [[DAOFactory factory] createRuntimeDAO:@"Event"];    
NSFetchedResultsController *fetchedResultsController = 
  [dao newFetchedResultsController:criteria sectionNameKeyPath:nil cacheName:@"Root"];

Points of interest

No documentation is included in this up-to-date version. Anyhow, the source code is self-explanatory and has altogether only a few hundred lines.

Any questions will be answered, feel free to contact me.

History

  • Summer 2009: Initial version.

License

This article, along with any associated source code and files, is licensed under The BSD License