2013-02-12 29 views
1

我遇到了一些核心数据后台处理问题。当我保存在我的后台上下文中时,似乎并没有将存储保存到主要上下文中。在调试我从后台线程注意到的执行保存操作的代码时,它似乎被暂停(?)此行为导致我获取过时的对象。核心数据后台处理,保存不推送到主要上下文

堆栈跟踪从节省:

Thread 29, Queue : NSManagedObjectContext Queue 
#0 0x9a5cf80e in semaphore_wait_trap() 
#1 0x02216f08 in _dispatch_thread_semaphore_wait() 
#2 0x02214b3a in _dispatch_barrier_sync_f_slow() 
#3 0x02214a5c in dispatch_barrier_sync_f() 
#4 0x01dfe03b in _perform() 
#5 0x01dfde9e in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]() 
#6 0x01ddb33c in -[NSManagedObjectContext save:]() 
#7 0x00096213 in __45-[CoreDataHelper saveInManagedObjectContext:]_block_invoke_0 at /Users/peterwarbo/Documents/Projects/MessagePlanr/MessagePlanr/CoreDataHelper.m:307 
#8 0x01e734b3 in developerSubmittedBlockToNSManagedObjectContextPerform_privateasync() 

保存方法:

- (void)saveInManagedObjectContext:(NSManagedObjectContext *)context { 

    if (context == nil) { 

     // Use default MOC 
     context = self.managedObjectContext; 

     NSError *error = nil; 

     if (context != nil) 
     { 
      if ([context hasChanges] && ![context 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. 
       */ 
       DLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       abort(); 
      } 
     } 

    } else { 

     // First save (child) context 
     [context performBlock:^{ 

      NSError *error = nil; 

      if ([context hasChanges] && ![context 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. 
       */ 
       DLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       abort(); 
      } 
     }]; 


     // Then save parent context 
     [self.managedObjectContext performBlock:^{ 

      NSError *error = nil; 

      if ([self.managedObjectContext hasChanges] && ![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. 
       */ 
       DLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       abort(); 
      } 
     }]; 
    } 
} 

这是保存方法,ReminderNSManagedObject,当操作完成我称之为结束块。然而,在完成块取一些NSManagedObjects他们没有被更新时(由于保存制止我相信?)

- (void)checkOverdueRemindersInBackgroundWithCompletionBlock:(void (^)(NSInteger overdueCount, NSArray *reminders))block { 

    DLogName() 

    // Creating a new MOC for thread safety 
    NSManagedObjectContext *syncContext = [self threadedManagedObjectContext]; 

    [syncContext performBlock:^{ 

     NSArray *reminders = [self fetchEntity:APReminderEntity predicate:nil andSortDescriptors:nil inManagedObjectContext:syncContext]; 

     NSInteger overdueCount = 0; 

     for (Reminder *reminder in reminders) { 

      [reminder checkOverdue]; // Checks if object is overdue and sets a flag if it is 

      [self saveInManagedObjectContext:syncContext]; 

      if (reminder.status.intValue == RMReminderStatusOverdue) { 

       overdueCount++; 
      } 

     } 

     block(overdueCount, reminders); 
    }]; 
} 

threadedManagedObjectContext方法:

- (NSManagedObjectContext *)threadedManagedObjectContext { 

    NSManagedObjectContext *threadedMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    threadedMoc.parentContext = self.managedObjectContext; //self.managedObjectContext is of type NSMainQueueConcurrencyType 

    return threadedMoc; 
} 
+0

在你的'saveInManagedObjectContext'方法中,尝试将你的父上下文保存在子上下文'performBlock'方法和'if'语句内部 – Yaman 2013-02-12 09:56:35

+0

@Yaman感谢您的建议,但这不是问题。在对performBlock * API进行一些调查之后,我自己发现了这个问题。 – 2013-02-12 13:06:02

+0

很高兴为你工作。你能用你找到的解决方案更新你的文章吗?它可以帮助其他民族有同样的问题。 – Yaman 2013-02-12 13:20:14

回答

1

的问题出现,是因为我” m使用performBlock:异步保存,它在返回时立即返回,并且我的完成块被调用,可能不会提交保存。

所以回答这个问题是内performBlockAndWait:

运行后台保存过程现在,另一个问题出现了,有没有使用任何performBlockAndWait:缺点?

相关问题