0

アプリを何年もクラッシュさせたバグを突き止めようとしています。しかし、原因が何であるかを絞り込むのに長い時間がかかりました.私は(ほぼ)それを持っていると思います. アプリがバックグラウンドに移行すると、バックグラウンド タスクが実行されてデータベースがクリーンアップされ、記事の順序が削除されてから 2 か月が経過します。

資格のある記事があり、この特定のリストを表示する UITableView が開いているNSFetchedResultsController場合、次のエラーで結果を照会することが多いため、アプリがクラッシュします。

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no section at index 26'

または時々:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

呼び出し時: (_objects は NSFetchedResultsController です)

[_objects objectAtIndexPath:[NSIndexPath indexPathForRow:currentRow inSection:indexPath.section]]

引き起こされた

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject

したがってNSFetchedResultsController、アプリがアクティビティを辞任したときに、バックグラウンド タスク/スレッドが (メイン スレッド上で) を (適切に) 利用できないためではないかと考えていました。それは説明ですか?もしそうなら、どうすればこの適切なフォームが発生するのを防ぐことができますか?

が変更をマージするのを防ぐことはできますが、アプリがフォアグラウンドに戻ったときにManagedObjectContect更新され、変更が に反映されていることを確認するにはどうすればよいですか?UITableView

理論だけ。バックグラウンド プロセスからクラッシュが発生することはわかっていますが、それ以上のことはまだありません。アプリがアクティブな場合、更新、削除、削除は正常に機能します。

コード修正による更新: バックグラウンド プロセスの呼び出し

- (void)performMaintenance{      
        UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance

        __block UIBackgroundTaskIdentifier background_task; //Create a task object

        background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
            [application endBackgroundTask: background_task]; //Tell the system that we are done with the tasks
            background_task = UIBackgroundTaskInvalid; //Set the task to be invalid

            //System will be shutting down the app at any point in time now
        }];

        //Background tasks require you to use asyncrous tasks

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            //Perform your tasks that your application requires

            NSLog(@"\n\nRunning maintenance in the background!\n\n");
            // Perform work that should be allowed to continue in background
            [self doMaintenance];

            [application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform
            background_task = UIBackgroundTaskInvalid; //Invalidate the background_task
        });
}


#pragma mark Actions
- (void)doMaintenance{
    DODataManager *data = [[DODataManager alloc] init];

    NSDateComponents *components = [[NSDateComponents alloc] init];
    components.month = -2;
    NSDate *twoMonthsBeforeNow = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:[NSDate date] options:0];

    NSFetchedResultsController* controller = [data getArticlesBeforeDate:twoMonthsBeforeNow];
    NSLog(@"Cleaning up database, removing %i items", controller.fetchedObjects.count);
    for(DOArticle* article in controller.fetchedObjects){
        [controller.managedObjectContext deleteObject:article];
    }

    // Update the unread count and unread count (if dataconenction available)
    [data updateBadge];

    [data commitChanges];

    data=nil;

    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObject:@"1.0" forKey:@"progress"];
    [[NSNotificationCenter defaultCenter] postNotificationName:kDialogUpdate object:dict];

    NSLog(@"Finished maintenace!");
}

クリーンアップは別のスレッドで適切に行われるようになり、通知はメイン スレッドに送信されますが、それでも同じ問題が発生します。

2014-01-27 22:16:34.541 iDomsPortalDev[1963:5107] Cleaning up database, removing 2 items
2014-01-27 22:16:36.024 iDomsPortalDev[1963:5107] Start for 3 items on object Setting!
2014-01-27 22:16:36.026 iDomsPortalDev[1963:5107] Removing 0 stat items
2014-01-27 22:16:36.029 iDomsPortalDev[1963:70b] Merging changes!
2014-01-27 22:16:36.030 iDomsPortalDev[1963:70b] Delete
4

1 に答える 1

1

非同期 GCD ブロックから doMaintainance を呼び出しており、その中でマネージド オブジェクト コンテキストにアクセスしています。

管理オブジェクト コンテキストはスレッド セーフではありません

于 2014-01-27T17:41:51.750 に答える