-[NSError retain]: 发送到释放实例的消息
-[NSError retain]: message sent to deallocated instance
启用 Zombies 后,我在以下 saveToURL 调用中收到标题错误(消息发送到已解除分配的 NSError 实例):
[aDocument saveToURL:aDocument.fileURL
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success) { ...
堆栈跟踪如下所示:
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];
});
}
}];
编辑:增加赏金
看来调用完成块代码的对象当时可能不存在,所以你需要一些方法来保持它的存活。
试试这个代码:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf documentSaved:aDocument forRestoredAssessment:patientAssessment];
});
如果您还有问题,请告诉我。
我相信我知道是什么原因造成的,因为我进行了以下更改,然后错误消失了。该错误很难解决,因为它没有直接指出这是原因。
我正在使用 UIDocumentSaveForOverwriting,但我发现有时该文件已被另一个进程删除。
因此,为了解决这个问题,我测试了文件是否存在,然后基于此使用了 UIDocumentSaveForOverwriting 或 UIDocumentSaveForCreating。
我们发现当父上下文有合并冲突时会出现这个僵尸。如果您在子类中覆盖 [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];
}
启用 Zombies 后,我在以下 saveToURL 调用中收到标题错误(消息发送到已解除分配的 NSError 实例):
[aDocument saveToURL:aDocument.fileURL
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success) { ...
堆栈跟踪如下所示:
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];
});
}
}];
编辑:增加赏金
看来调用完成块代码的对象当时可能不存在,所以你需要一些方法来保持它的存活。
试试这个代码:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf documentSaved:aDocument forRestoredAssessment:patientAssessment];
});
如果您还有问题,请告诉我。
我相信我知道是什么原因造成的,因为我进行了以下更改,然后错误消失了。该错误很难解决,因为它没有直接指出这是原因。
我正在使用 UIDocumentSaveForOverwriting,但我发现有时该文件已被另一个进程删除。
因此,为了解决这个问题,我测试了文件是否存在,然后基于此使用了 UIDocumentSaveForOverwriting 或 UIDocumentSaveForCreating。
我们发现当父上下文有合并冲突时会出现这个僵尸。如果您在子类中覆盖 [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];
}