我有一个问题,我无法理解如何处理因为逻辑上没有发生。
我有一些同时运行的NSOperation
个。例如,
- (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
吗?这是由于不同的线程和不同的对象?我该如何解决这个问题?
答案 0 :(得分:2)
移动您用于合并app delegate中的更改的代码。
因此,在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];
}
P.S。在这里,您使用的是非并发NSOperation
,如果插入NSOperationQueue
,将以并发方式运行(队列,通过GCD将为您管理)。
答案 1 :(得分:1)
这不是并发操作。并且您的mergeChanges
通知可能永远不会被调用,因为一旦main方法完成,操作将被解除分配(可能在NSManagedObjectContextDidSaveNotification
选择器执行之前)。
如果您希望并行操作在完成之前一直存在,则需要覆盖start
方法和isConcurrent
方法。您可能会收到此错误,因为您的NSError
或选择器在完成之前超出了范围。我建议阅读本文以了解并发与非并发操作的工作原理:
请查看Dave Dribin的Concurrent Operations Demystified了解更多详情。