CoreDataの基礎 その1|CoreDataの基礎 その2|CoreDataの基礎 その3|CoreDataの基礎 その4
実際にデータを保存してみる。
結論から言ってハマりました。。。
まず、.xcdatamodelでのEntityの設定で以下のようにしました。
・Entity名:User ・アトリビュート キー:no int16 氏名:name String
で、ですね、「SELECT * FROM User WHERE no = 2;」みたいなことをやろうと、
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(no = %d)", i];
を実行してもまったくもって抽出できない! 文字列のフォーマットが駄目なのか?と何度も検証したが何度やってもうまくいかないorz で、判明したのが、
アトリビュート名で「no」を使うと抽出できなかった・・・
SQLiteの予約語なのか?Core Dataで利用できないのか?わからないが、アトリビュート名を 「no」→「id」に変更したらうまくいきました。 ※idはObjective-Cの予約語なのでこれも命名的によろしくないとは思いますが・・・
駄目駄目なかなり汚いコードですが・・・まぁ、調査と言う事で。
- (void)applicationDidEnterBackground:(UIApplication *)application {
Core_Data_persistenceAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
for (int i = 1; i <= 4; i++) {
NSString *fieldName = [NSString stringWithFormat:@"line%d", i];
UITextField *textField = [self valueForKey:fieldName];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"User"
inManagedObjectContext:context];
[request setEntity:entityDescription];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(id = %d)", i];
[request setPredicate:pred];
NSManagedObject *user = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(@"Error!");
}
if ([objects count] > 0) {
//UPDATE
user = [objects objectAtIndex:0];
} else {
//INSERT
user = [NSEntityDescription insertNewObjectForEntityForName:@"User"
inManagedObjectContext:context];
}
[user setValue:[NSNumber numberWithInt:i] forKey:@"id"];
[user setValue:textField.text forKey:@"name"];
[request release];
}
[context save:&error];
}
- (void)viewDidLoad {
NSLog(@"viewDidLoad");
Core_Data_persistenceAppDelegate *appDelegate =
[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"User"
inManagedObjectContext:context];
[request setEntity:entityDescription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
[request release];
if (objects == nil) {
NSLog(@"Error!");
}
for (NSManagedObject *oneObject in objects) {
NSNumber *rid = [oneObject valueForKey:@"id"];
NSString *name = [oneObject valueForKey:@"name"];
UITextField *textField = [self valueForKey:fieldName];
textField.text = name;
}
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app
];
[super viewDidLoad];
}
(1) applicationDidEnterBackgroundが呼び出される (2) ApplicateionDelegateからNSManagedObjectContextを取得 (3) NSEntityDescription entityForNameでUser Entityを取得 (4) データベースリクエストである (5) NSFetchRequest setPredicateでクエリーを設定
SELECT * FROM User WHERE id = %d
(6) (NSArray *) NSManagedObjectContext executeFetchRequest:NSFetchRequestでクエリー実行 (7) 既にデータがある場合はNSArrayの最初のデータ(NSManagedObject)取得 (8) データがない場合はNSEntityDescription insertNewObjectForEntityForNameでNSManagedObjectを新規作成 (9)setValueで各値を設定し、NSManagedObjectContext saveで保存
(1) viewDidLoadが呼び出される (2) ApplicateionDelegateからNSManagedObjectContextを取得 (3) NSEntityDescription entityForNameでUser Entityを取得 (4) NSFetchRequest setPredicateでクエリーを設定 (5) (NSArray *) NSManagedObjectContext executeFetchRequest:NSFetchRequestでクエリー実行 (6) NSArrayをループして、valueForKeyでデータ設定
また、viewDidLoadでapplicationDidEnterBackgroundのObserverを設定しています。 ただ、Applicationの遷移でデータを制御するのは危険かと思うのであくまでも一例で・・・