0

論理的に発生しないため、処理方法が理解できない問題があります。

NSOperation同時に実行される sがいくつかあります。例えば、

- (void)main
{
    @autoreleasepool
    {        
        AppDelegate *appController = (AppDelegate *)[[UIApplication sharedApplication] delegate];

        self.managedObjectContext = [[NSManagedObjectContext alloc] init];
        [self.managedObjectContext setUndoManager:nil];
        [self.managedObjectContext setPersistentStoreCoordinator: [appController persistentStoreCoordinator]];

        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
        [nc addObserver:self
               selector:@selector(mergeChanges:) 
                   name:NSManagedObjectContextDidSaveNotification
                 object:self.managedObjectContext];
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription 
                                       entityForName:@"Entity" inManagedObjectContext:self.managedObjectContext];
        [fetchRequest setEntity:entity];

        [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"%K != %@",@"number1",[NSNumber numberWithInt:2]]];

        NSError *error;
        NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

        for (NSManagedObject *obj in fetchedObjects) {

            //Do Something with managed object then save        
            NSError *error = nil;
            //[episode release];
            if (![self.managedObjectContext save:&error]) {
                // Replace this implementation with code to handle the error appropriately.
                // abort() causes the application to generate a crash log and terminate.
                // You should not use this function in a shipping application, although it may be useful
                // during development. If it is not possible to recover from the error, display an alert
                // panel that instructs the user to quit the application by pressing the Home button.
                //
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }
    }
}

- (void)mergeChanges:(NSNotification *)notification
{
    AppDelegate *appController = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *mainContext = [appController managedObjectContext];

    // Merge changes into the main context on the main thread
    [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
                              withObject:notification
                           waitUntilDone:YES];  
} 

これは私の典型的なものNSOperationで、同時に動作し、コア データ内のオブジェクトを更新し、説明なしでアプリがクラッシュし、次の行にそのエラーが表示されることがあります。

if (![self.managedObjectContext save:&error])

私のクラッシュ レポートでは、私の質問は、アプリのクラッシュを防ぎ、エラーを修正する方法はありますか? @syncronizedを演奏するときに を使用できますsaveか? これは、異なるスレッドと異なるオブジェクトによるものですか? どうすればこれを修正できますか?

4

2 に答える 2

2

アプリ デリゲートの変更をマージするために使用するコードを移動します。

application:didFinishLaunchingWithOptions:そのため、通知の登録内で。

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
[nc addObserver:self
       selector:@selector(mergeChanges:) 
           name:NSManagedObjectContextDidSaveNotification
         object:nil]; // set nil here

次に、常にアプリ デリゲート内でmergesChanges:メソッドを作成します。ここでは、通知がメイン スレッドで実行され、通知を受け取ったコンテキストがメイン スレッドとは異なることを確認する必要があります。

- (void)mergeChanges:(NSNotification *)notification
{
    if ([notification object] == [self managedObjectContext])
        return;

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(mergeChanges:) withObject:notification waitUntilDone:YES];
        return;
    }

    NSManagedObjectContext *mainContext = [self managedObjectContext];

    // Merge changes into the main context on the main thread
    [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
                              withObject:notification
                           waitUntilDone:YES];  
}

NSOperationPSここでは、に挿入された場合に並行して実行される非並行を使用してNSOperationQueueいます(GCDを使用したキューがこれを管理します)。

于 2013-01-13T12:00:05.203 に答える
1

これは同時操作ではありません。またmergeChanges、メイン メソッドが終了するとすぐに操作の割り当てが解除されるため (おそらくNSManagedObjectContextDidSaveNotificationセレクターが実行される前に)、通知が呼び出されることはありません。

完了するまで継続する並行操作が必要な場合は、startメソッドとisConcurrentメソッドをオーバーライドする必要があります。NSErrorまたはセレクターが完了する前に範囲外になるため、おそらくこのエラーが発生しています。この記事を読んで、同時操作と非同時操作がどのように機能するかを理解することをお勧めします。

詳細については、Dave Dribin によるDemystified Concurrent Operationsを参照してください。

于 2013-01-13T04:29:08.523 に答える