Restkit and deadlock



目前我正在使用Restkit来控制我的应用程序中的所有(核心)数据。我使用它来使用RKManagedObjectMapping与服务器保持同步,并使用[myNSManagedObject createEntity]与[[RKObjectManager§sharedManager].objectStore save]一起手动编辑Grand Central Dispatch中的项目。

有没有建议用这种方式或其他方式来做这件事?因为有时应用程序在执行Restkit 的代码时会冻结在死锁中

+ (NSArray*)objectsWithFetchRequest:(NSFetchRequest*)fetchRequest {
    NSError* error = nil;
    NSArray* objects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    if (objects == nil) {
        RKLogError(@"Error: %@", [error localizedDescription]);
    }
    return objects;
}

使用

- (NSError*)save {
    NSManagedObjectContext* moc = [self managedObjectContext];
    NSError *error;
    @try {
        if (![moc save:&error]) {
            if (self.delegate != nil && [self.delegate respondsToSelector:@selector(managedObjectStore:didFailToSaveContext:error:exception:)]) {
…

并行。在我切换到Restkit之前,我在每个编辑代码的实体周围都放了一个"context-performBlockAndWait",这是安全的,没有死锁。我没有其他NSManagedObjectContext或我自己创建的东西,都来自Restkit。

在我的例子中,问题是我跨线程边界传递NSManagedObjects,并在线程上使用它们,而不是在从它们各自的NSManagedObjectContext中提取它们的线程上。在我的情况下,这真的很微妙,因为我知道我不应该这么做,但无论如何我都是意外地这么做的。我没有传递托管对象,而是开始传递NSManagedObjectID(然后从本地线程的MOC获取),从那以后就没有遇到死锁。我建议您对代码进行深入扫描,以确保您只在派生托管对象的线程中使用托管对象。

我们在应用程序中遇到了这个精确问题。基本上,CoreData嵌套上下文在iOS5中非常有缺陷,因此不能像宣传的那样工作。这有很多表现形式,但其中之一就是上面描述的问题,即获取请求与后台操作之间的死锁。这是一个很好的记录,有指导意义的引用:

NSFetchedResultsController死锁

您永远不希望应用程序死锁。使用NSFetchedResultsController和嵌套上下文,这很容易做到。使用与上述相同的UIManagedDocument设置,在私有队列上下文中执行提取请求,同时将NSFetched ResultsControl与主队列上下文一起使用,很可能会出现死锁。如果你在大约同一时间开始这两种情况,它几乎100%一致。NSFetchedResultsController可能正在获取一个不该获取的锁。据报道,对于即将发布的iOS,这一问题已得到修复。

这个SO答案有一个可能的修复程序,可以保留嵌套的上下文。我见过其他类似的情况,基本上是自由地应用-performAndWait:调用。我们还没有尝试过(iOS5在我们的用户群中有个位数的百分比)。否则;"修复";我们现在知道的是放弃iOS5的嵌套上下文(参见这个SO答案)。

CoreData在多线程(iOS 5中)方面继续受到根本性的破坏,这对苹果来说是不可原谅的。现在你可以很好地证明,在CoreData(多线程,iCloud)上信任苹果似乎正在打开一个痛苦的袋子。

最新更新