Core Data(Data Access Object)

Next topic is Data Access object.
What is data access object. It’s kind of design pattern.
To retrieve data from CoreData, we need some codes. That means data access.
To write getting and setting CoreData code in Model, that is one choice.
But, this model may be changed. And these file are generated from XCode.
So, I recommend that we create new file for Data Access Object.

This idea is from Java.
I’m a Java Programmer too.
DAO is to find, findAll, create, delete, update, etc..

Example

CoreData data model is in other entry Core Data(File xcdatamodeld).

Let’s go codes!

SettingDAO.h

#define kSetting @"Setting"
#define kNumber @"number"
#define kKey @"key"
#define kValue @"value"

@interface SettingDAO : NSObject
-(void)createSetting:(NSManagedObjectContext *)context
              number:(int)number
                 key:(NSString *)key
               value:(int)value;
-(Setting *)findByNumber:(NSManagedObjectContext *)context number:(int)number;
-(void)update:(NSManagedObjectContext *)context number:(int)number value:(int)value;
@end

SettingDAO.m

@implementation SettingDAO

-(NSFetchRequest *)getRequest:(NSManagedObjectContext *)managedObjectContext
{
    NSEntityDescription *entity = [NSEntityDescription entityForName:kSetting inManagedObjectContext:managedObjectContext];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];
    return request;
}

-(void)createSetting:(NSManagedObjectContext *)context
number:(int)number
key:(NSString *)key
value:(int)value
{
    NSManagedObject *newSetting = [NSEntityDescription insertNewObjectForEntityForName:kSetting inManagedObjectContext:context];
    
    [newSetting setValue:[NSNumber numberWithInt:number] forKey:kNumber];
    [newSetting setValue:key forKey:kKey];
    [newSetting setValue:[NSNumber numberWithInt:value] forKey:kValue];
}

-(Setting *)findByNumber:(NSManagedObjectContext *)context number:(int)number
{
    NSFetchRequest *request = [self getRequest:context];
    NSString *predicateString = [NSString stringWithFormat:@"number == \"%d\"", number];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setPredicate:predicate];
    return [[context executeFetchRequest:request error:nil] objectAtIndex:0];
}

-(void)update:(NSManagedObjectContext *)context number:(int)number value:(int)value
{
    NSManagedObject *obj = [self findByNumber:context number:number];
    [obj setValue:[NSNumber numberWithInt:value] forKey:kValue];
    
    NSError *error = nil;
    if ( ![context save:&error] )
    {
        NSLog(@"Fail Update");
    }
}
@end

NSManagedObjectContext is imperative.

ColorDAO.h

#define kColor @"Color"
#define kR @"r"
#define kG @"g"
#define kB @"b"
#define kAlpha @"alpha"

@interface ColorDAO : NSObject
-(void)createColor:(NSManagedObjectContext *)context
            number:(int)number
               key:(NSString *)key
                 r:(int)r
                 g:(int)g
                 b:(int)b
             alpha:(double)alpha;
-(Color *)findByNumber:(NSManagedObjectContext *)context number:(int)number;
-(NSArray *)findAll:(NSManagedObjectContext *)context;
@end

ColorDAO.m

@implementation ColorDAO

-(NSFetchRequest *)getRequest:(NSManagedObjectContext *)managedObjectContext
{
    NSEntityDescription *entity = [NSEntityDescription entityForName:kColor inManagedObjectContext:managedObjectContext];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];
    return request;
}

-(void)createColor:(NSManagedObjectContext *)context
              number:(int)number
                 key:(NSString *)key
               r:(int)r
                 g:(int)g
                 b:(int)b
             alpha:(double)alpha
{
    NSManagedObject *newColor = [NSEntityDescription insertNewObjectForEntityForName:kColor inManagedObjectContext:context];
    
    [newColor setValue:[NSNumber numberWithInt:number] forKey:kNumber];
    [newColor setValue:key forKey:kKey];
    [newColor setValue:[NSNumber numberWithInt:r] forKey:kR];
    [newColor setValue:[NSNumber numberWithInt:g] forKey:kG];
    [newColor setValue:[NSNumber numberWithInt:b] forKey:kB];
    [newColor setValue:[NSNumber numberWithDouble:alpha] forKey:kAlpha];
}

-(Color *)findByNumber:(NSManagedObjectContext *)context number:(int)number
{
    NSFetchRequest *request = [self getRequest:context];
    NSString *predicateString = [NSString stringWithFormat:@"number == \"%d\"", number];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setPredicate:predicate];
    return [[context executeFetchRequest:request error:nil] objectAtIndex:0];
}

-(NSArray *)findAll:(NSManagedObjectContext *)context
{
    NSFetchRequest *request = [self getRequest:context];
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"number" ascending:YES];
    [request setSortDescriptors:[NSArray arrayWithObject:sorter]];
    return [context executeFetchRequest:request error:nil];
}

@end

MemoDAO.h

#define kMemo @"Memo"
#define kUID @"uid"
#define kBody @"body"
#define kDate @"lastmodified"
#define kColorVal @"color"
@interface MemoDAO : NSObject
-(void)createMemo:(NSManagedObjectContext *)context
             body:(NSString *)body
            color:(Color *)color
             date:(NSDate *)date;
-(Memo *)findByUid:(NSManagedObjectContext *)context uid:(NSString *)uid;
-(NSArray *)findAll:(NSManagedObjectContext *)context;
-(NSArray *)findNumbers:(NSManagedObjectContext *)context limit:(int)limit number:(int)number;
-(NSArray *)findNumbersByColor:(NSManagedObjectContext *)context limit:(int)limit number:(int)number color:(Color *)color;
-(int)countMemo:(NSManagedObjectContext *)context;
-(int)countMemoByColor:(NSManagedObjectContext *)context color:(Color *)color;
-(void)updateMemo:(NSManagedObjectContext *)context uid:(NSString *)uid body:(NSString *)body color:(Color *)color;
-(void)deleteMemo:(NSManagedObjectContext *)context uid:(NSString *)uid;
@end

MemoDAO.m

@implementation MemoDAO

-(NSFetchRequest *)getRequest:(NSManagedObjectContext *)managedObjectContext
{
    NSEntityDescription *entity = [NSEntityDescription entityForName:kMemo inManagedObjectContext:managedObjectContext];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];
    return request;
}

-(void)createMemo:(NSManagedObjectContext *)context
             body:(NSString *)body
               color:(Color *)color
             date:(NSDate *)date
{
    NSManagedObject *newMemo = [NSEntityDescription insertNewObjectForEntityForName:kMemo inManagedObjectContext:context];
    
    NSManagedObjectID *new_id = [newMemo objectID];
    NSString *str = [[new_id URIRepresentation] lastPathComponent];
    NSString *key = [str stringByReplacingOccurrencesOfString:@"-" withString:@""];
    
    [newMemo setValue:key forKey:kUID];
    [newMemo setValue:body forKey:kBody];
    [newMemo setValue:date forKey:kDate];
    [newMemo setValue:color forKey:kColor];
    
    NSError *error = nil;
    if ( ![context save:&error] )
    {
        NSLog(@"Error when creating memo");
    }
}

-(Memo *)findByUid:(NSManagedObjectContext *)context uid:(NSString *)uid
{
    NSFetchRequest *request = [self getRequest:context];
    NSString *predicateString = [NSString stringWithFormat:@"uid == \"%@\"", uid];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setPredicate:predicate];
    return [[context executeFetchRequest:request error:nil] objectAtIndex:0];
}

-(int)countMemo:(NSManagedObjectContext *)context
{
    NSError *error = nil;
    NSFetchRequest *request = [self getRequest:context];
    NSUInteger count = [context countForFetchRequest:request error:&error];
    return count;
}

-(int)countMemoByColor:(NSManagedObjectContext *)context color:(Color *)color
{
    NSError *error = nil;
    NSFetchRequest *request = [self getRequest:context];
    NSString *predicateString = [NSString stringWithFormat:@"color.number == \"%d\"", [color.number intValue]];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    [request setPredicate:predicate];
    NSUInteger count = [context countForFetchRequest:request error:&error];
    return count;
}

-(NSArray *)findAll:(NSManagedObjectContext *)context
{
    NSFetchRequest *request = [self getRequest:context];
    return [context executeFetchRequest:request error:nil];
}

-(NSArray *)findNumbers:(NSManagedObjectContext *)context limit:(int)limit number:(int)number
{
    NSFetchRequest *request = [self getRequest:context];
    [request setFetchLimit:limit];
    [request setFetchOffset:number];
    NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:kDate ascending:NO];
    [request setSortDescriptors:[NSArray arrayWithObject:sortByDate]];
    return [context executeFetchRequest:request error:nil];
}

-(NSArray *)findNumbersByColor:(NSManagedObjectContext *)context limit:(int)limit number:(int)number color:(Color *)color
{
    NSFetchRequest *request = [self getRequest:context];
    [request setFetchLimit:limit];
    [request setFetchOffset:number];
    NSString *predicateString = [NSString stringWithFormat:@"color.number == \"%d\"", [color.number intValue]];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
    NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:kDate ascending:NO];
    [request setPredicate:predicate];
    [request setSortDescriptors:[NSArray arrayWithObject:sortByDate]];
    return [context executeFetchRequest:request error:nil];
}

-(void)updateMemo:(NSManagedObjectContext *)context uid:(NSString *)uid body:(NSString *)body color:(Color *)color {
    
    NSManagedObject *memo = [self findByUid:context uid:uid];
    if ( memo != nil )
    {
        [memo setValue:body forKey:kBody];
        [memo setValue:color forKey:kColor];
        
        NSError *error = nil;
        if ( ![context save:&error] )
        {
            NSLog(@"Error when creating memo");
        }
    }
}

-(void)deleteMemo:(NSManagedObjectContext *)context uid:(NSString *)uid {
    NSManagedObject *obj = [self findByUid:context uid:uid];
    if ( obj != nil ) {
        [context deleteObject:obj];
    }
}
@end

Actually, we can create more complicated condition predicator.
Core Data may cover SQL statement.