UIManagedDocument を使用してアプリを動作させることを扱っています。数日前に別の質問を投稿しましたが、まだ機能していません。これをもっとうまくできるか見てみましょう。
私のアプリは、plist ファイルからいくつかのデータをロードし、それをデータベースに入力する必要があります。次に、時々変更されるいくつかのパラメーターがあり、それらをデータベースにロードして更新する必要もあります。
アプリは次の順序に従う必要があります: データベースを作成/開き、データをロードし、変数データを更新します。
私の問題は、そのシーケンスを正しくたどろうとしたときに発生します。これは主に、すべてのオブジェクトがデータベースに作成される前に変数データを更新できない (したがって、更新する必要がある nil 変数) ためであり、私の回避策は予期しない結果につながるだけです。クラッシュと非論理的な行動。
ここ'
ビューコードでは:
- (void)viewDidLoad{
[super viewDidLoad];
self.database = [DataHelper opendatabaseAndUseBlock:^{
[self setupFetchedResultsController]; // I pass this method trough a Block because I want it
// to be executed once the database is opened, not before.
}];
}
次に、次のコードを含むこのヘルパー クラス「DataHelper」を使用します。
@implementation DataHelper
// This method creates and opens the database, then calls the necessary methods
+ (UIManagedDocument *)openDatabaseAndUseBlock:(completion_block_t)completionBlock
{
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"Database"];
UIManagedDocument *database = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[database.fileURL path]]) {
[database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
[self loadDataIntodatabase:database withSuccess:success];
completionBlock();
}];
} else if (database.documentState == UIDocumentStateClosed) {
[database openWithCompletionHandler:^(BOOL success) {
[self loadDataIntodatabase:database withSuccess:success];
completionBlock();
}];
} else if (database.documentState == UIDocumentStateNormal) {
[self loadDataIntodatabase:database withSuccess:YES];
completionBlock();
}
return database;
}
// This method loads the "static" data into the database, by reading it from a plist file.
// Once the loading finishes, it should call the last method, for updating the variable data
+ (void)loadDataIntoDatabase:(UIManagedDocument *)database withSuccess:(BOOL)success
{
if (success) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
NSArray *plistData = [NSArray arrayWithContentsOfFile:path];
[database.managedObjectContext performBlock:^{
for (NSDictionary *data in plistData) {
[Object createObjectWithData:data inManagedObjectContext:database.managedObjectContext];
}
// Not sure what to do here!!
//[database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
// [DataHelper updateVariableDataOfDatabase:database];
//}];
// Or...?
//[database updateChangeCount:UIDocumentChangeDone];
// [DataHelper updateVariableDataOfDatabase:database];
}];
} else {
NSLog(@"NO SUCCESS");
}
}
// This last method updates some parameters of the existing data
// in the database, to the ones found in another plist file
+ (void)updateVariableDataOfDatabase:(UIManagedDocument *)database
{
// This path is provisional, should be gotten from an online resource
NSString *path = [[NSBundle mainBundle] pathForResource:@"VariableData" ofType:@"plist"];
NSDictionary *variables = [NSDictionary dictionaryWithContentsOfFile:path];
[database.managedObjectContext performBlock:^{
// Update the objects changing the values of the variable parameters
// to the ones found in "variables"
// Now I should save the changes, or maybe not?
//[database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:nil];
// Or...
//[database updateChangeCount:UIDocumentChangeDone];
}];
}
@end
「saveToURL」メソッドを使用すると、正しくないように見えますが、すべてのデータがデータベースにロードされるまで最後のメソッドが実行されないため、ロード シーケンスが正しく実行されます。ただし、多くの操作を実行しようとすると、アプリがランダムにクラッシュします (削除、更新、再読み込みなど、多くの節約が行われます)。
一方、「updateChangeCount」を使用すると、アプリはクラッシュしなくなりますが、シーケンスはうまく機能しません。変数データは更新されず、アプリはそこにあるオブジェクトを見つけられません。データベースなど。各アクションの間に2分ほど待つと、はい、機能します...しかし、それは私が望んでいることではありません.
ここで助けていただければ幸いです。これは私の時間を浪費しており、このプロジェクトの締め切りはかなり間近です :( どうも
ありがとうございました!