O/R Mapping Framework for iPhone Development in Objective-C using Active Object pattern.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Classes
OCActiveObjects.xcodeproj
Tests
build/OCActiveObjects.build/OCActiveObjects.pbxindex
ActiveObjectTest.h
ActiveObjectTest.m
ActiveObjectTestCase.h
ActiveObjectTestCase.m
LICENSE
OCActiveObjects-Info.plist
OCActiveObjects_Prefix.pch
README.textile
Test Suite-Info.plist
cheatsheet.txt
main.m

README.textile

OCActiveObjects

Vision:

Create a simple O/R mapping library for Sqlite in iPhone SDK.

Mission Statement:

Provide an Active Object pattern based O/R mapping library for iPhone development. Apply convention over configuration to simplify installation and development.

Installation:

Git it from http://github.com/bhatti/OCActiveObjects/tree/master and add to your XCode

Design:

This library is fairly small and consists of following classes:

ActiveObject

This is base class that you extend in order to add automatic O/R support. You have to override following Class methods to specify name of the database and table:

+ (NSString *) getTableName;
+ (NSString *) getDatabaseName;
You will then be able to call following methods to interact with the Sqlite database:
+ (void) openDatabase;
Above method must be called once before any other methods, usually at the start of your application.

+ (void) closeDatabase;
Above method must be called once before you shutodnw your application.

  
  - (void) save;

Above method saves a new object or updates an existing object. Each subclass of
ActiveObject is automatically assigned a unique database id with a property
named “objectId”. If that property is nil then it assumes this is new object and
inserts a new row in the database, otherwise it updates an existing row in the
database. It assumes that name of database fields are same as property names,
though you can override that behavior by overriding _getPropertyNamesAndTypes
Class method.



+ (ActiveObject *) findByPrimaryKey:(NSNumber *)objId;

Above method queries an object in the database matching objectId property, which
identifies each object in the database.

  + (NSArray *) findWithCriteria:(NSDictionary *)criteria;

Above method returns an array of objects that match criteria. The criteria at
this time is simple dictionary, i.e., pair of name and values that are joined by
AND” clause. There is a immediate need to extend this to support more flexible
queries.



+ (NSArray *) findAll;

Above method returns all objects, which may not be good for iPhone application
due to limited amount of memory. This is another area that needs immediate
attention.

  + (int) removeAll;

Above method removes all rows in the table so be careful with this.

  + (int) removeWithCriteria:(NSDictionary *)criteria;

Above method removes only methods matching criteria. Again criteria consists of
name/value pairs.

  + (int) countWithCriteria:(NSDictionary *)criteria;

Above method counts the number of rows in the database matching criteria.

  + (int) countAll;

Above method returns count of all rows in the table.

Exension Methods in ActiveObject


There are number of extension methods to customize SQLs or behavior of the
object such as

- (void) _insert;

- (void) _update;

+ (NSDictionary *) _getPropertyNamesAndTypes;

+ (NSArray *) _getPropertyNames;

+ (NSArray *) _getPropertyNamesWithoutObjectId;

+ (NSMutableString *) _getFieldNamesAsStringWithObjectId:(BOOL) useObjectId;

+ (NSString *) _getCreateSQL;

+ (NSMutableString *) _getInsertSQL;

+ (NSMutableString *) _getUpdateSQL;

+ (NSMutableString *) _getSelectSQL;

+ (void) _createTable;

+ (NSString *) _toWhere:(NSArray *)names;

IntrospectHelper

The OCActiveObjects library uses some Objective C magical runtime support to
query for properties and this class encapsulates those methods.

SqliteHelper


This class some helper methods for Sqlite3.

How to use

In order to test it, let’s define a simple Person class that extends
ActiveObject, e.g.


#import <Foundation/Foundation.h>
#import “ActiveObject.h”

@interface Person : ActiveObject {
NSString *name;
short age;
int rank;
long votes;
char sex;
double income;
BOOL active;
NSInteger flags;
NSNumber *rating;
NSDate *birthdate;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) short age;
@property (nonatomic, assign) int rank;
@property (nonatomic, assign) long votes;
@property (nonatomic, assign) char sex;
@property (nonatomic, assign) double income;
@property (nonatomic, assign) BOOL active;
@property (nonatomic, assign) NSInteger flags;
@property (nonatomic, retain) NSNumber *rating;
@property (nonatomic, retain) NSDate *birthdate;

- (BOOL)isEqualToPerson:(Person *)aPerson;

@end

Implemention of Person.m looks like:


#import “Person.h”

@implementation Person
@synthesize name;
@synthesize age;
@synthesize rank;
@synthesize votes;
@synthesize sex;
@synthesize income;
@synthesize active;
@synthesize flags;
@synthesize rating;
@synthesize birthdate;

- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToPerson:other];
}

- (BOOL)isEqualToPerson:(Person *)aPerson {
if (self == aPerson)
return YES;
if (![(id)[self name] isEqual:[aPerson name]])
return NO;
return YES;
}

- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
return hash;
}

- (NSString *)description {
return [NSString stringWithFormat:"id %, name %, age %d, rank %d, votes %d, sex %c, income %f, active %d, flags %d, rating %, birthdate %@",
self.objectId, self.name, self.age, self.rank, self.votes, self.sex, self.income, self.active, self.flags, self.rating, self.birthdate];
}

- (void) dealloc {
[name release];
[birthdate release];
[super dealloc];
}

+ (NSString *) getTableName {
return @"persons";
}

+ (NSString *) getDatabaseName {
return @"personsdb";
}

@end

Then you can first open the database, e.g.

 
[Person openDatabase];

Then create a new person object, e.g.


Person *person = [[[Person alloc] init] autorelease];
person.birthdate = [[NSDate alloc]init];
int random = [person.birthdate timeIntervalSince1970];
person.age = random % 30;
person.rank = random % 20;
person.votes = random % 10;
person.sex = ‘M’;
person.name = [NSString stringWithFormat:@"Joe #%d", random % 1000];
person.income = random % 3000;
person.active = YES;
person.flags = random % 30 + 0.5;
person.rating = [NSNumber numberWithInt:20.5];
return person;

You will then be able to save the person object as


[person save];

You can see how many rows are in the database by

int count = [Person countAll];

And then retrieve the object that we saved as


Person *person2 = (Person *) [Person findByPrimaryKey:person.objectId];


When you are done, you can then close the database:


[Person closeDatabase];

Backlog:

  • add better criteria support
  • add paging support
  • add XCode framework support to integrate easily with other applications
  • add more tests
  • add relational mapping
  • add validation support