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
idinfo = [ [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];
ブログの記法上、もしかしたら記号とかが正しく表示されていないかもしれないが、そこは心眼でカバー。(・ω・)
これらは、実際に動いているモノをスクラッチで書き直したもの、なので抜け・漏れは多いにありうる!
このまま動作する保証は無いけど、やっている事は合っていると思います。
個人的に回りくどい感じは否めないので、これらの煩雑な儀式的記述を隅に追いやるインターフェイスを書いて、実装すると吉かもしれない。