2014-01-20 41 views
0

我仍然很难理解核心数据如何在后台线程中工作,即使在阅读了很多关于它的事情后,尤其是删除对象。删除核心数据对象并保存在后台线程中

举个例子,如果我想删除这样的背景下一个对象:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     // Delete object from database 
     [context deleteObject:[self.tests objectAtIndex:indexPath.row]]; 
     NSError *error = nil; 
     if (![context save:&error]) { 
      NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
      return; 
     } 
     [self.tests removeObjectAtIndex:indexPath.row]; 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

这个工作,但是当数据量大,[context save:&error]需要花费大量的时间,所以我该怎么办它在后台? 看来我不能用另一个上下文工作,否则我得到错误an nsmanagedobjectcontext cannot delete objects in other contexts。 我已经尝试了数百种不同的东西,但我迷失了... 谢谢!

回答

0

查看NSManagedObjectContext上的performBlock和performBlockAndWait方法。

我一直赞成使用NSPrivateQueueConcurrencyType,即使我的UI绑定托管对象上下文,因为它避免了这种情况。例如,你可以做这样的事情:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     NSManagedObject *m = [self.tests objectAtIndex:indexPath.row]; 
     [context performBlock:^{ 
      [context deleteObject:m]; 

      if (![context save:&error]) { 
       //Note: You should really do something more useful than log this 
       NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
      } 
     }]; 
     [self.tests removeObjectAtIndex:indexPath.row]; 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

的performBlock调用是异步的(而不是其同步对应performBlockAndWait),这将允许的tableView继续更新的背景是在一个单独的线程忙于拯救。

另外,您的托管对象上下文实例不应该经常更改。小型应用程序在其生命周期中仅分配一个NSManagedObjectContxt实例是很常见的。

+0

谢谢!这似乎工作。我只是想知道:是否可以只使用NSPrivateQueueConcurrencyType? – jcr

+0

只要您使用performBlock/perfomBlockAndWait从管理对象中读取它就没有问题。 Tableview代码特别有点尴尬,因为你必须从performBlockAndWait调用中复制这些值,将它们设置在单元格中。从NSMainQueueConcurrencyType开始(因此您可以在块中设置单元格属性),然后转换为专用队列(如果有意义)。 – ImHuntingWabbits

1

您只能删除objectcontext;在其中您获取该托管对象。如果您正在使用seprate thread新的背景下,在这种情况下,你应该从managedObjectobjectId从第一个方面得到了这样你就可以删除对象

[context objectWithID:objectId]]; 

的NSManagedObjectID是上下文之间的相同,但NSManagedObject本身不是。

+1

(1)假设托管对象在持久存储中 –

+0

任何crud操作都将在上下文中完成... –

1

作为提到的其他答案,您只能从其上下文中删除一个对象,并且上下文是线程绑定的。这里的问题不是保存需要多长时间,而是您保存的位置。

您应该避免在任何面向像这样的方法调用的UI中进行昂贵的操作。删除后没有理由立即保存。稍后保存,当用户预期UI延迟时保存。核心数据将工作得很好,没有保存。

相关问题