首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EXC_BAD_ACCESS在NSFileVersion调用removeOtherVersionsOfItemAtURL时:内部协调写块

EXC_BAD_ACCESS在NSFileVersion调用removeOtherVersionsOfItemAtURL时:内部协调写块
EN

Stack Overflow用户
提问于 2012-09-05 01:57:35
回答 1查看 357关注 0票数 5

我在协调编写块中使用了NSFileVersion类方法removeOtherVersionsOfItemAtURL:的简单调用,用于解决iCloud冲突。

当我的设备进入“spaz模式”(这是一个技术术语,用于在几个设备上重复打开和关闭应用程序)时,会在内部引发EXC_BAD_ACCESS异常。代码片段:

代码语言:javascript
复制
- (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行上,正如您从下面的屏幕截图中可以看到的那样,它深入到了苹果代码领域。

Link to image of debugger

在提交雷达之前,我想我应该检查一下,看看我是不是做错了什么?第1402行中的额外[... copy]只是一个快速检查,以确保我不会丢失对块提供的参数的引用,并且将被删除。

编辑:是一个重要的笔记!我在用ARC。

编辑2:我在调用时注意到:

[NSFileVersion otherVersionsOfItemAtURL:theURL]

返回值为nil,它指示(通过文档):

如果没有这样的文件,...or为零。数组不包含currentVersionOfItemAtURL:方法返回的version对象。

因此,通过在调用removeOtherVersionsOfItemAtURL:之前检查该方法的返回值,它缓解了这个问题。但我仍然感到奇怪的是,抛出了一个EXC_BAD_ACCESS,而不是正确处理它的那个方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-05 11:57:53

我注意到当我打电话时:

[NSFileVersion otherVersionsOfItemAtURL:theURL]

在调用removeOtherVersionsOfItemAtURL:之前,返回值为零,指示(通过文档):

返回:一个文件版本对象数组,如果没有这样的文件,则为零。数组不包含currentVersionOfItemAtURL:方法返回的version对象。

因此,通过在调用removeOtherVersionsOfItemAtURL:之前检查该方法的返回值,它缓解了这个问题。但是,我仍然感到奇怪的是,EXC_BAD_ACCESS是由removeOtherVersionsOfItemAtURL:抛出的,而不是只返回NO或填充提供的NSError对象的方法。

我会把雷达归档,等我收到消息后会在这里更新。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12273548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档