2012-05-09 23 views
0

私はUIManagedDocumentを使用して自分のアプリケーションの作業を処理しています。私は数日前に別の質問を投稿しましたが、私はまだそれを働かせていません。私がこれをもっとうまくやれるかどうか見てみましょう。
私のアプリは、plistファイルからいくつかのデータを読み込んでデータベースに書き込む必要があります。次に、何度も変更されるいくつかのパラメータがあります。また、それらをデータベースにロードして更新する必要もあります。
アプリケーションは次のシーケンスに従ってください。データベースの作成/オープン、データのロード、変数データの更新。
私の問題は、データベースにすべてのオブジェクトが作成される前に変数のデータを更新できないため(そして、更新する必要があるnil変数)、そのシーケンスを正しく実行しようとすると、予期しないクラッシュや非論理的な振る舞いにつながります。
ここに私のコードは、これまでのところです:ビューのコードでUIManagedDocumentを正しく初期化、使用、保存する方法

- (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分ほど待っていたら、それはうまくいく...しかし、それは私が望むものではありません。

私は、これは私の時間を消費しており、このプロジェクトの期限がかなり:(
どうもありがとうございました!

答えて

0

の近くにいくつかの時間が経過しているとうまくいけば、あなたはすでにきている、ここではいくつかの助けを本当に感謝しますここであなたの問題を解決しましたが、過去数ヶ月間UIManagedDocument関連の問題を自分自身で解決しようとしているので、私はあなたの痛みを感じます。あなたがここでやっていることは、最近のプロジェクト

残念ながら、UIManagedDocumentを一般的な方法で保存する(または保存しない)方法についてはオンライン上に浮かんでいるドキュメントやさまざまな提案場所のどこかにあるようだ。私はsaveToURLとupdateChangeCountの両方のアプローチを使用して同様の結果を見出しましたが、updateChangeCountアプローチはあまり頻繁に保存エラーを引き起こすようです。しかし、私はあなたの問題に本当に影響しているとは思わない。

文書にアクセスするスレッドが1つのみで、データに対して1つの文書しか開いていない限り、実際には保存する必要はありません。自動的にそのコンテキスト内に保存されます。そのコンテキストから他のコンテキスト(UIManagedDocumentには2つあります)への変更をプッシュし、最終的にクラウドやその他のデバイスに出力するには、保存が必要です。 completionHandler内にperformBlockの2つのレイヤーがあります。複雑なことがあり、複数のスレッドが同時にデータベースにアクセスしている可能性があります。私がすべてのプリロードと設定を行うと、completionHandlerの中で順番に順番に実行され、opendatabaseAndUseBlockに相当するものが続き、クラッシュすることはありません。

関連する問題