zpa*_*ack 5 macos cocoa nstextview
我编写了一个NSTextView子类,它对文本本身进行频繁的编程修改(有点像IDE的代码格式化 - 例如自动插入紧密括号).
我最初的实现使用了NSTextView insertText:.这实际上看起来完全正常.但是在阅读NSTextView文档时(我有时会为了好玩),我在讨论部分注意到了insertText:
此方法是插入用户键入的文本的入口点,通常不适用于其他目的.最好通过直接对文本存储进行操作来对文本进行编程修改.
哦,我的坏,我想.因此,我尽职尽责地将所有insertText调用更改为对底层NSTextStorage(replaceCharactersInRange:withString:主要是)的调用.这似乎工作正常,直到我注意到它完全搞砸了Undo(当然,因为Undo是由NSTextView处理的,而不是NSTextStorage).
所以在我把文件存储器中的buncha撤销代码拖出来之前,我想知道我insertText:是不是Punk'd,真的不是那么糟糕?
是的,所以我的问题是:NSTextView的insertText:调用真的"不适合"编程修改NSTextView的文本,如果是的话,为什么呢?
insertText:是一种方法NSResponder- 通常这些将被视为响应用户事件的方法.在某种程度上,它们意味着"用户行为".当文档告诉您NSTextStorage如果要以编程方式更改内容时直接编辑,则"编程"一词用于区分用户意图和应用程序操作.如果您希望您的更改可以撤消,就像它们是用户操作一样,那么insertText:似乎可以使用它.也就是说,大多数情况下,如果修改不是由用户操作启动的,那么用户将不会认为它是可撤销的操作,并且使其成为可撤销操作的单元将导致混淆.
例如,假设我在文本视图中粘贴了一个单词"foo",然后您的应用程序将该单词着色为红色(无论出于何种原因).如果我然后选择撤消,我希望我的行动是撤消的,而不是着色.着色不是我的用户意图的一部分.如果我再次打击Cmd-Z以实际取消我的动作,我就会想,"WTF?"
NSUndoManager支持通过beginUndoGrouping和分组事件endUndoGrouping.这可以允许用户意图单元(粘贴操作)与应用程序着色分组为单个"撤消单元".在最简单的情况下,你可能会想尝试这里是设置groupsByEvent在NSUndoManager为YES,然后找到一个方法来触发应用程序的行为在runLoop同通的用户行为发生.这将导致NSUndoManager自动分组.
除此之外,如果您的程序化修改需要异步或某种形式,您需要自己以某种方式管理这些分组,但这可能是非常重要的实现.