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在表演时使用 asave吗?这是由于不同的线程和不同的对象造成的吗?我怎样才能解决这个问题?

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];  
}

PS在这里,您使用的是非并发NSOperation的,如果插入到 aNSOperationQueue中,它将以并发方式运行(队列,通过 GCD 将为您管理)。

于 2013-01-13T12:00:05.203 回答
1

这不是并发操作。而且您的mergeChanges通知可能永远不会被调用,因为一旦 main 方法完成,操作就会被释放(这可能会在NSManagedObjectContextDidSaveNotification选择器执行之前)。

如果你想要一个在你完成之前一直存在的并发操作,你需要重写start方法和isConcurrent方法。您可能会收到此错误,因为您的NSErroror 选择器在完成之前超出了范围。我建议阅读这篇文章以了解并发与非并发操作的工作原理:

有关更多详细信息,请查看Dave Dribin 揭秘的并发操作。

于 2013-01-13T04:29:08.523 回答