昨日に続いて、coredataの使い方で躓いてしまったので、また残す事にする。
coredataのデータ更新自体は、サンプルのソースがたくさん出ていて、特に悩む事はないと思う。
しかし、今回は、うまく更新が出来ない現象に当たってしまった。
しかも、シミュレータでは、特に問題なく動作したのだが、実機を使うと失敗してしまった。
この手の現象が最も困ってしまう。
今回は、データベースのデータ構造として、少し複雑な構造を設計していた。
昨日の記事にも書いている事から分かるように、独自のクラスを追加して、データに使用した。
それだけであれば、おそらく問題は出なかったと思う。
データの構造を簡単に書くと、メインの配列があり、そのメンバに、さらに配列を作り、メンバが独自クラスという構造。
簡単に書くとい可能なイメージ。
メインのcoredataから管理するデータ(xcdatamodeldに書いてあるメンバ)
@interface DataGroup : NSManagedObject
NSString *sampleName;
NSMutableArray *arrayObject;
(このNSMutableArrayは、実際には、Transformable)
NSMutableArray *sampleObject;に設定する内容として、下記のクラスを作成
@interface DataObject : NSObject
NSString *itemName;
UIImage *itemObject;
double itemDouble;
こんな感じ。
データの更新タイミングで、単純に変更したパラメータのみ設定して書き込みを行う。
その上で、再読み込みをすると、設定した内容を取り出す事が出来た。
これで問題ないと思って、次の作業を行っていたのだが、しばらくして実機で確認した。
すると、更新して保存、再読み込みと特に問題なく出来たのだが、アプリを再起動して読み込むと、データが消えている。
「arrayObject」に新規の「DataObject」のメンバを追加して保存するのだが、アプリ再起動後は、メンバがいなくなる。
シミュレータで同じ事を行うと、アプリ再起動後も正しく再設定した内容が取り出せる。
この中途半端さ加減に参ってしまった。
いろいろ考えた結果、失敗するパターンの事のみ考えて、下記のような対策を行った。
「arrayObject」に入っているクラスそのものは、使い回していたのをやめて、新規に作成する事にした。
下記が、対応後のソース
DataGroup *selectedObject = [[self fetchedResultsController] objectAtIndexPath:editGroupNo];
NSMutableArray *editArray = selectedObject.arrayObject;
DataObject *editData = [[DataObject alloc]init];
[editArray addObject:editData];
NSMutableArray *saveArray = [NSMutableArray array];
NSInteger cnt,loopMax;
loopMax = editArray.count;
for (cnt=0; cnt<loopMax; cnt++) {
[saveArray addObject:[editArray objectAtIndex:cnt]];
}
selectedObject.pinArrayObject = saveArray;
// saveメソッドで更新状態を確定
error = nil;
if (![context save:&error]) {
NSLog(@"error = %@", error);
abort();
}
これで、メンバの追加がうまくいくようになった。
しかし、独自クラス内のメンバの内容を更新しても変更されない現象が続けて発生した。
たとえば、上記の構想の「itemName」のみを変更してアプリを起動したままし読み込みをすると、変更されていた。
しかし、アプリを再起動すると、変更前のデータが出てきた。
これも、シミュレータで同じ事を行うと、アプリ再起動後も正しく再設定した内容が取り出せる。
このような現象が起きてしまったら、あまり行いたくない事であったが、一度、削除してから再設定を行う事で、対策する事が出来た。
DataGroup *selectedObject = [[self fetchedResultsController] objectAtIndexPath:editGroupNo];
NSMutableArray *editArray = selectedObject.arrayObject;
DataObject *editData = [editArray objectAtIndex:editItemNo];
selectedObject.pinArrayObject = nil;
// saveメソッドで更新状態を確定
error = nil;
if (![context save:&error]) {
NSLog(@"error = %@", error);
abort();
}
editData.itemName = @"変更後の文字列";
NSMutableArray *saveArray = [NSMutableArray array];
NSInteger cnt,loopMax;
loopMax = editArray.count;
for (cnt=0; cnt<loopMax; cnt++) {
[saveArray addObject:[editArray objectAtIndex:cnt]];
}
selectedObject.pinArrayObject = saveArray;
// saveメソッドで更新状態を確定
error = nil;
if (![context save:&error]) {
NSLog(@"error = %@", error);
abort();
}
これで、メンバ内のデータ更新がうまくいくようになった。
coredataは使いやすいような使いにくいような、なかなか謎が多いのかもしれない。
[0回]
PR