Cra*_*tis 5 xcode objective-c ios
我正在使用似乎是在协调写入块内部的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);
}
});
}
Run Code Online (Sandbox Code Playgroud)
我认为一点语法高亮可能会使这更容易检查:
错误实际上发生在第1404行,正如您从下面的屏幕截图中看到的那样,它在Apple代码区域中很深.
在提交雷达之前,我想我会在这里查看是否有什么我做错了?[... copy]1402行的额外内容只是一个快速检查,以确保我没有丢失对块提供的参数的引用,并将被删除.
编辑:一个重要的说明!我正在使用ARC.
编辑2:我注意到在打电话时:
[NSFileVersion otherVersionsOfItemAtURL:theURL]
返回值是nil,表示(通过文档):
...如果没有这样的文件,则为零.该数组不包含currentVersionOfItemAtURL:方法返回的版本对象.
因此,通过在调用之前检查此方法的返回值removeOtherVersionsOfItemAtURL:,可以缓解此问题.但我仍然觉得抛出EXC_BAD_ACCESS很奇怪,而不是正确处理它的方法.
我在打电话时注意到:
[NSFileVersion otherVersionsOfItemAtURL:theURL]
在调用之前removeOtherVersionsOfItemAtURL:,返回值为 nil,这表明(通过文档):
返回: 文件版本对象数组,如果不存在该文件则返回 nil。该数组不包含 currentVersionOfItemAtURL: 方法返回的版本对象。
因此,通过在调用之前检查此方法的返回值removeOtherVersionsOfItemAtURL:,它缓解了这个问题。但我仍然觉得奇怪的是, anEXC_BAD_ACCESS是由 抛出的removeOtherVersionsOfItemAtURL:,而不是该方法简单地返回NO,或者简单地填充提供的NSError对象。
我将提交一份雷达报告,并在收到回复后在此更新。
| 归档时间: |
|
| 查看次数: |
324 次 |
| 最近记录: |