*

iPhoneアプリ CoreDataでのCRUD

まずは前準備。


// モデルを作る
NSManagedObjectModel *model = [ [NSManagedObjectModel mergedModelFromBundles:nil] retain];

// コーディネータを作る
NSPersistentStoreCoordinator *coordinator;

NSURL *url = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

NSString *storePath = [(NSString *)url stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", @"MyAppli", @"sqlite"] ];

NSFileManager *fileManager = [NSFileManager defaultManager];

if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [ [NSBundle mainBundle] pathForResource:@"MyAppli" ofType:@"sqlite"];

if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}

NSURL *storeUrl = [NSURL fileURLWithPath:storePath];

NSPersistentStoreCoordinator *coordinator = [ [NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) abort();

// コンテクストを作る
NSManagedObjectContext *context = [ [NSManagedObjectContext alloc] init];

[context setPersistentStoreCoordinator:coordinator];

つらつらーっと書いたけど、実際はメソッドを分けたりgetterとかでうまい具合にやりましょう。


Create


NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"MyTable" inManagedObjectContext:context];
[object setValue:@"john" forKey:@"name"];
[object setValue:@"1" forKey:@"gender"];

NSError *error = nil;

[context save:&error];

if (error) NSLog(@"error occurred");

これもメソッドを分けたり、エラー処理はデリゲータでやらせたり(ry


Retrieve


NSMutableArray *returnArray = [ [NSMutableArray alloc] init];

NSFetchRequest *request = [ [NSFetchRequest alloc] init];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyTable" inManagedObjectContext:context];

[request setEntity:entity];

// search condition (optional)
/*
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"gender = %@", @"1"];
[request setPredicate:predicate];
*/

// order (required)
NSSortDescriptor *sortDescriptor = [ [NSSortDescriptor alloc] initWithKey:@"name" ascending:TRUE];
NSArray *sortDescriptors = [ [NSArray alloc] initWithObjects:sortDescriptor, nil];

[request setSortDescriptors:sortDescriptors];

[sortDescriptor release];
[sortDescriptors release];

// limit (optional)
/*
int limit = 10;
[request setFetchBatchSize:limit];
*/

// execution
NSFetchedResultsController *result = [ [NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:@"Root"];

[request release];

NSError *error = nil;

[result performFetch:&error];

if (error) NSLog(@"error occurred");

// get result infomation
id info = [ [result sections] objectAtIndex:0];

// collect results
for (int i = 0; i < [info numberOfObjects]; i++) {
NSManagedObject* record = [result objectAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0] ];
[returnArray addObject:record];
}

return returnArray;
}

これもメソッドを分けたり、例外処理(ry


Update
(resultは既にデータ取得したNSFetchedResultsControllerとする)


NSManagedObject* record = [result objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] ];

[record setValue:@"new john!" forKey:@"name"];
[record setValue:@"2" forKey:@"gender"];

NSError *error = nil;

[context save:&error];

if (error) NSLog(@"error occurred");

(ry


Delete
(resultは既にデータ取得したNSFetchedResultsControllerとする)


NSManagedObject* record = [result objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] ];

[context deleteObject:record];

NSError *error = nil;

[context save:&error];

if (error) [delegate onErrorOccured:error];



ブログの記法上、もしかしたら記号とかが正しく表示されていないかもしれないが、そこは心眼でカバー。(・ω・)

これらは、実際に動いているモノをスクラッチで書き直したもの、なので抜け・漏れは多いにありうる!

このまま動作する保証は無いけど、やっている事は合っていると思います。

個人的に回りくどい感じは否めないので、これらの煩雑な儀式的記述を隅に追いやるインターフェイスを書いて、実装すると吉かもしれない。