【发布时间】:2014-01-11 08:02:46
【问题描述】:
我有一个基于NSDocument 的 OS X 应用程序,它不会使用空白页面创建新文档,而是向用户显示一个面板以供从中选择模板,例如 Apple 的 Pages.app。
我通过在用户启动一个新文档时手动创建一个新的 NSDocument 实例并立即在其上设置一个属性来反映用户为其选择的模板来做到这一点:
MyNSDocumentSubclass *newDoc = [sharedDocumentController makeUntitledDocumentOfType:fileType error:&err];
[newDoc setTemplate:templateChosenByUser]; // autosave doesn't care about this line
[sharedDocumentController addDocument:newDoc];
[newDoc makeWindowControllers];
[newDoc showWindows];
在用户决定重新启动计算机或关闭应用程序而不保存之前,这可以正常工作:当 App Kit 的自动保存功能尝试在下次启动时恢复我的应用程序的以前状态时,它无法为用户模板属性执行此操作因为它从来没有注意到MyNSDocumentSubclass'模型状态已经改变并且没有自动保存整个文档。相反,可能出于性能优化的原因,它只是创建了一个新的MyNSDocumentSubclass 实例,并且用户的模板选择丢失了。
为了解决这个问题,我添加了
[newDoc updateChangeCount:NSChangeDone];
反映用户选择模板引入的模型机会。现在,自动保存正确启动,并在计算机或应用程序关闭之前保存文档。唯一的缺点(以及我在这里寻求帮助的问题)是,这是错误的做法:NSChangeDone 旨在反映用户发起的文档模型的机会。因此,它会导致“已编辑”已显示在新文档的窗口中,并在关闭窗口时向用户显示保存面板。但是,用户的模板选择并不是真正应该算作“编辑”的更改,因为它与新文档的创建紧密相关。幸运的是,OS X 发行说明正是讨论了这个问题并提供了解决方案:
某些应用程序使用
-updateChangeCount:导致NSDocument自动保存并非直接源自用户的更改。例如,当导入非本地文档类型时,某些应用程序会使用导入的内容创建一个新文档并调用 -updateChangeCount:以确保文档自动保存这些内容。许多应用程序为此目的使用NSChangeDone。但是,由于用户没有明确地导致此更改,因此不希望将此文档变成草稿。应用程序应小心使用正确的NSDocumentChangeType——在本例中为NSChangeReadOtherContents——以防止转换为草稿。使用NSChangeDiscardable也会阻止草稿的创建。
不幸的是,[newDoc updateChangeCount:NSChangeReadOtherContents] 根本不起作用。它肯定会抑制窗口标题中的“已编辑”,但同时它会阻止自动保存在终止应用程序时完成其工作:文档不会自动保存并在下次启动时丢失其模板属性的值。
那么,我该怎么办? 我希望我新创建的NSDocument 子类能够自动保存用户的模板选择。同时,它不应该显示为已经被用户编辑,而实际上他们只是创建了它。
我唯一能想到的就是尝试使用NSWindowRestoration 协议来保存模板属性,但这显然是错误的。此外,在文档重新打开过程中,窗口恢复启动得太晚了。
我的另一个想法是为用户可以选择的每个模板创建几个不同的 NSDocument 子类(由具有单个 UTI 的不同文件类型反映),而不是在我的 NSDocument 子类上使用属性——但这感觉还是不对的。
否则,我迷路了。感谢您的帮助。
【问题讨论】:
标签: objective-c macos cocoa nsdocument autosave