最初にいくつかのデータを UIManagedDocument にロードしてから実行するアプリケーションがありますsaveToURL:forSaveOperation:completionHandler:
。completionHandler ブロック内で、このデータベースのさまざまな要素の更新を行い、それが完了すると、別の保存を行います。
それに加えて、アプリには、データの再読み込み、データの再更新、およびデータベースの 1 つのエンティティの削除をそれぞれ行う 3 つのボタンがあります。どのボタン方式でも、最後の命令は節約にもなります。
これらすべてをシミュレーターで実行すると、すべてがスムーズに進みます。しかし、デバイスではそうではありません。常にクラッシュします。通常、「削除」ボタンを押すか、データベースを再ロードまたは再更新するとクラッシュすることがわかりました。そして、それは常にsaveToURL
操作にあります。私の意見では、データベースを保存するスレッド
が複数ある場合に問題が発生します。デバイスのコード実行が遅くなると、複数の節約が同時に発生し、アプリがそれらを正しく処理できなくなる可能性があります。また、削除ボタンでエンティティが削除されず、エンティティが存在しないと表示される場合があります (存在する場合)。
私はこれに完全に困惑しており、このすべての保存操作を実行する必要があります...実際、それらを削除すると、アプリはさらに一貫性のない動作をします。
この問題を解決するために何ができるかについての提案はありますか? どうもありがとうございました!
[編集] ここに問題のあるコードを投稿します。最初にデータをロードするために、ヘルパー クラスを使用します。具体的には、次の 2 つのメソッドを使用します。
+ (void)loadDataIntoDatabase:(UIManagedDocument *)database
{
[database.managedObjectContext performBlock:^{
// Read from de plist file and fill the database
[database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
[DataHelper completeDataOfDatabase:database];
}];
}
+ (void)completeDataOfDatabase:(UIManagedDocument *)database
{
[database.managedObjectContext performBlock:^{
// Read from another plist file and update some parameters of the already existent data (uses NSFetchRequest and works well)
// [database saveToURL:database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:nil];
[database updateChangeCount:UIDocumentChangeDone];
}];
}
ビューには、次のような 3 つのアクション メソッドがあります。
- (IBAction)deleteButton {
[self.database.managedObjectContext performBlock:^{
NSManagedObject *results = ;// The item to delete
[self.database.managedObjectContext deleteObject:results];
// [self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
[self.database updateChangeCount:UIDocumentChangeDone];
}];
}
- (IBAction)reloadExtraDataButton {
[DataHelper loadDataIntoDatabase:self.database];
// [self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
[self.database updateChangeCount:UIDocumentChangeDone];
}
- (IBAction)refreshDataButton {
[DataHelper completeDataOfDatabase:self.database];
//[self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
[self.database updateChangeCount:UIDocumentChangeDone];
}
[編集 2] コードの追加: まず、最初のビューは次のように viewDidLoad を実行します。
- (void)viewDidLoad{
[super viewDidLoad];
self.database = [DataHelper openDatabaseAndUseBlock:^{
[self setupFetchedResultsController];
}];
}
setupFetchedResultsController メソッドは次のようになります。
- (void)setupFetchedResultsController
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Some entity name"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.database.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
アプリの各ビュー (タブがあります) には、データベースに含まれるさまざまなエンティティを表示するために、異なる setupFetchedResultsController があります。
ヘルパー クラスでは、これが各ビューの viewDidLoad を介して実行される最初のクラス メソッドです。
+ (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];
completionBlock();
}];
} else if (database.documentState == UIDocumentStateClosed) {
// Existe, pero cerrado -> Abrir
[database openWithCompletionHandler:^(BOOL success) {
[self loadDataIntoDatabase:database];
completionBlock();
}];
} else if (database.documentState == UIDocumentStateNormal) {
[self loadDataIntoDatabase:database];
completionBlock();
}
return database;
}