objective-c – NSFileVersion调用期间EXC_BAD_ACCESS调用remove
我正在使用似乎是NSFileVersion类方法removeOtherVersionsOfItemAtURL的简单调用:在一个协调的写入块内部进行一些iCloud冲突解决.
当我的设备进入“spaz模式”时,这是在少数设备上反复打开和关闭应用程序的技术术语,会在内部抛出EXC_BAD_ACCESS异常.代码段: - (void)compareVersionChanges:(NSFileVersion *)version { if (![DataLoader iCloudPreferenceEnabled]) { NSLog(@"Ignoring iCloud changes (version comparison) based on user preference"); return; } NSLog(@"compareVersionChanges"); dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); dispatch_async(aQueue,^(void) { NSError *readError = nil; NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:(id)self]; [coordinator coordinateReadingItemAtURL:[version URL] options:0 error:&readError byAccessor:^(NSURL *newURL) { DataContext *loadedContext = nil; NSData *data = [NSData dataWithContentsOfURL:newURL]; NSError *e = nil; loadedContext = [self convertXmlDataToContext:data error:&e]; if (e) { NSLog(@"Done loading,error: %@",e); [[DataLoader applicationDelegate] displayError:e]; loadedContext = nil; } if (!loadedContext) { return; } id appDelegate = [DataLoader applicationDelegate]; DataContext *inMemoryContext = nil; if (appDelegate != nil && [appDelegate respondsToSelector:@selector(context)]) { inMemoryContext = [appDelegate performSelector:@selector(context)]; } if (inMemoryContext) { NSLog(@"Performing iCloud context synchronizating..."); DataContextSynchronizer *synchronizer = [[DataContextSynchronizer alloc] init]; ChangeSet *changes = [synchronizer compareLocalContext:inMemoryContext andRemoteContext:loadedContext]; if ([[changes changes] count] > 0) { [SelectionManager disable]; @synchronized(appDelegate) { NSLog(@"Applying synchronization changes..."); [synchronizer applyChangeSet:changes toDataContext:inMemoryContext]; NSLog(@"Synchronization changes applied"); } [SelectionManager enable]; if ([appDelegate respondsToSelector:@selector(setSkipRefreshSave:)]) { [appDelegate performSelector:@selector(setSkipRefreshSave:) withObject:[NSNumber numberWithBool:YES]]; } dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue,^(void) { [SelectionManager notifyListeners]; }); if ([appDelegate respondsToSelector:@selector(setSkipRefreshSave:)]) { [appDelegate performSelector:@selector(setSkipRefreshSave:) withObject:[NSNumber numberWithBool:NO]]; } [self save:[[DataLoader applicationDelegate] context]]; } else { NSLog(@"No sync changes applicable."); } NSError *coordinateWriteRemoveError = nil; [coordinator coordinateWritingItemAtURL:newURL options:NSFileCoordinatorWritingForDeleting error:&coordinateWriteRemoveError byAccessor:^(NSURL *theURL) { theURL = [theURL copy]; NSError *removeOtherVersionsError = nil; [NSFileVersion removeOtherVersionsOfItemAtURL:theURL error:&removeOtherVersionsError]; if (removeOtherVersionsError) { NSLog(@"Error removing other versions: %@",removeOtherVersionsError); } }]; if (coordinateWriteRemoveError) { NSLog(@"Error occurred coordinating write for deletion of other file versions: %@",coordinateWriteRemoveError); } } }]; if (readError) { NSLog(@"Done loading (outside block) error: %@",readError); } }); } 我认为一点语法高亮可能会使这更容易检查: Link to image of code snippet and failure stack in Xcode 错误实际上发生在第1404行,正如您从下面的屏幕截图中看到的那样,它在Apple代码区域中很深. Link to image of debugger 在提交雷达之前,我想我会在这里查看是否有什么我做错了?第1402行的额外[… copy]只是一个快速检查,以确保我没有丢失对块提供的参数的引用,并将被删除. 编辑:一个重要的说明!我正在使用ARC. 编辑2:我注意到在打电话时: [NSFileVersion otherVersionsOfItemAtURL:theURL] 返回值为nil,表示(通过文档):
因此,在调用removeOtherVersionsOfItemAtURL:之前检查此方法的返回值,可以缓解此问题.但我仍然觉得抛出EXC_BAD_ACCESS很奇怪,而不是正确处理它的方法. 解决方法
我注意到在打电话时:
[NSFileVersion otherVersionsOfItemAtURL:theURL] 在调用removeOtherVersionsOfItemAtURL:之前,返回值为nil,表示(通过文档):
因此,可以缓解此问题.但我仍然觉得奇怪的是,removeOtherVersionsOfItemAtURL:抛出EXC_BAD_ACCESS,而不是简单地返回NO的方法,或者只是填充提供的NSError对象. 我将提交雷达,当我收到回复时会在这里更新. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |