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):
- (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:
DAOFactory *factory = [DAOFactory factory];
DAO *dao = [factory createRuntimeDAO:@"EntityName"];
You can extend DAOFactory
and implement factory methods for your custom DAOs:
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:
-(NSArray*)findAllId;
-(NSArray*)findAll;
-(NSArray*)findAll:(NSUInteger)fetchOffset limit:(NSUInteger)limit;
-(NSArray*)findAllId:(CDSearchCriteria*)criteria;
-(NSArray*)findAll:(CDSearchCriteria*)criteria;
-(NSArray*)findAll:(CDSearchCriteria*)criteria
fetchOffset:(NSUInteger)fetchOffset limit:(NSUInteger)limit;
-(NSUInteger)count;
-(NSUInteger)count:(CDSearchCriteria*)criteria;
-(NSManagedObject*)insertNewObject;
-(void)deleteObject:(NSManagedObject*)object;
-(NSManagedObject*)findObjectById:(NSManagedObjectID*)objectID;
- (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.
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.
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.
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:
@"function name:property name"
For example:
@"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'.
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:
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.