我已经在 Apple 的开发者论坛上发布了这个问题,一周后没有收到任何回复,所以我希望我能在这里有更好的运气。
我创建了一个标准的基于文档的应用程序(使用 NSDocument,保存简单的 XML 文件),现在我需要扩展它以将文档范围的书签保存到用户选择的外部文件中。
一切正常,除了文档范围的书签在我从文件中读回它们后无法解析之外,事实证明这是由于 NSDocument 以原子方式写入文件。
背景
因为我发现通过 Apple 的开发者论坛或网络搜索很难找到有关报告错误的信息,所以我将快速记录我发现的内容,以防它对同一条船上的其他人有所帮助。
失败尝试返回的错误是:
错误域 = NSCocoaErrorDomain 代码 = 256 “无法打开文件“somefile.xml”。”
其中,令人困惑的是,somefile.xml 是(文件名组件)在下面的代码块中作为“relativeToURL:”传递的绝对 URL。
有App Sandbox:document-scoped bookmark notsolving等报告;启用原子文件保存时,不返回任何表明沙盒/书签存在问题的错误。
这个问题之前的报告没有给出同样的错误(他们通常指的是没有错误信息的失败),但是我创建了一个单独的测试应用程序(不使用 NSDocument)来测试这个,发现我能够重现写入文件时使用以下代码与上述相同的错误消息:
// HACK: Save a temporary value to the file so that the file exists when creating the bookmark
NSString *temp = @"Temp";
[temp writeToURL:saveURL atomically:NO encoding:NSUTF8StringEncoding error:&error];
// Create bookmark to imageURL relative to the save location
NSData *bookmarkData = [imageURL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:[saveURL absoluteURL] error:&error];
if(bookmarkData == nil) return;
// Convert NSData to a string format.
NSString *bookmarkString = [bookmarkData base64EncodedString];
// Write the file.
[bookmarkString writeToURL:saveURL atomically:YES encoding:NSUTF8StringEncoding error:&error];
将最后一行更改为“atomically:NO”时,书签会正确解析,并且一切都按预期工作。
NSDocument 和原子写作
由于 NSDocument 的默认和推荐设置使用原子写入,并且这不适用于 Sandbox 的核心功能之一,我正在寻找一种方法使文档范围的书签和 NSDocument 一起工作,我认为这意味着找到一种方法来使 NSDocument 直接而不是原子地写入文件。
我还没有找到解决 Apple 框架故障的任何有效解决方案(在这些论坛上或更广泛的搜索中)。
我可以覆盖其中之一
- writeSafelyToURL:ofType:forSaveOperation:error:
- writeToURL:ofType:forSaveOperation:错误:
- saveToURL:ofType:forSaveOperation:completionHandler:
但在每种情况下,文档都说“如果您覆盖此方法,请务必调用超类实现”,这可能会继续以原子方式保存文件。
我的目标是以一种我可以继续支持 Apple 推动开发人员(无论好坏)的其他用户体验期望的方式来做到这一点 - 例如。autosavesInPlace、版本等。但我愿意牺牲这些细节,以便有一个可以发布到 AppStore 的工作沙盒应用程序。