- [NSError retain]:发送到解除分配的实例的消息

时间:2016-12-09 02:44:03

标签: objective-c memory-management nserror nszombie uimanageddocument

启用Zombies后,我在以下saveToURL调用中收到标题中的错误(发送给NSError的解除分配实例的消息):

[aDocument saveToURL:aDocument.fileURL
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success) { ...

堆栈跟踪如下所示:

enter image description here

aDocument是UIManagedDocument的子类的实例。我有并发调试,我看看是否有任何线程冲突,还没有找到任何。我该怎么调试呢?

编辑:还尝试了以下代码,同时发生了崩溃

__weak typeof(self) weakSelf = self;

    [aDocument saveToURL:aDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
        if (success) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf documentSaved:aDocument forRestoredAssessment:patientAssessment];
            });
        }
    }];

编辑:bounty添加

3 个答案:

答案 0 :(得分:2)

我们发现,当父上下文具有合并冲突时,就会发生此僵尸。如果您在子类中覆盖[UIManagedDocument writeContents:toURL:forSaveOperation:originalContentsURL:error]方法,请使用以下方法访问父上下文:NSManagedObjectContext *context = [(NSDictionary *)contents objectForKey:@"parentContext"];。如果存在更改,请使用以下标准代码保存父上下文。如果通过设置合并策略或重置上下文解决了冲突,则僵尸将不会发生。

- (BOOL)writeContents:(id)contents
                toURL:(NSURL *)url
     forSaveOperation:(UIDocumentSaveOperation)saveOperation
  originalContentsURL:(NSURL *)originalContentsURL
                error:(NSError * _Nullable __autoreleasing *)outError {

    NSError *error = nil;

    NSManagedObjectContext *context = self.managedObjectContext.parentContext;

    if (context.hasChanges) {
        [context performBlockAndWait:^{

            NSError *saveError = nil;
            if (![context save:&saveError]) {
                NSLog(@"Document Writing: error saving context %@", saveError);
                [context reset];
            }
        }];
    }
    return [super writeContents:contents
                          toURL:url
               forSaveOperation:saveOperation
            originalContentsURL:originalContentsURL
                          error:outError];
}

答案 1 :(得分:0)

我相信我弄明白是什么造成了这种情况,因为我做了以下更改然后错误就消失了。这个错误很难解决,因为它没有直接指出这是原因。

我使用的是UIDocumentSaveForOverwriting,但我发现有时该文件已被其他进程删除。

所以要解决我测试文件存在的问题,然后根据它使用UIDocumentSaveForOverwriting或UIDocumentSaveForCreating。

答案 2 :(得分:-1)

似乎调用完成块代码的对象可能不在那个时候,所以你需要一些方法来保持它的存活。

试试这段代码:

__weak typeof(self) weakSelf = self;

dispatch_async(dispatch_get_main_queue(), ^{
    [weakSelf documentSaved:aDocument forRestoredAssessment:patientAssessment]; 
});

如果您仍然遇到问题,请告诉我。