在Mavericks中,Apple在NSScrollView
中引入了响应式滚动架构。此功能添加了一种智能方法,用于生成透支,并将传入滚动事件的处理从主事件循环解耦为单独的事件循环。 in the session 215 from WWDC 2013详细介绍了该主题。
由于事件模型不同,滚动事件不再通过scrollWheel(with:)
方法。实际上,如果在NSScrollView
子类中重写此方法,则完全退出响应式滚动体系结构并退回到传统模型。
在我的NSScrollView
中,我想在按住命令键的同时使用滚动实现放大的交互。这可以在MindNode或OmniGraffle应用程序中观察到。执行此操作的标准方法是覆盖scrollWheel(with:)
并检查每个滚动事件上的modifierFlags
。如上所述,这将导致从响应滚动模型退出。
我想知道是否有一种方法来实现这种交互,同时还保留响应式滚动?
我已经实现/尝试过的内容:
NSScrollView
子类中,我已经覆盖了scrollWheel(with:)
,并从静态属性true
返回isCompatibleWithResponsiveScrolling
,以强制参与响应式滚动。super
并让NSScrollView
执行其操作。如果按下命令键,我会转到不同的路径并跟踪窗口上的下一个滚动事件以进行放大。flagsChanged(with:)
并且可以观察到这一刻何时发生,但我还没有找到一种方法来结束滚动。 This SO question询问有关结束/禁用滚动但尚未回答的问题。我将在这里回答,而不是在评论中,因为我有更多的数据。
“响应式滚动”有两个问题:
(1)几年前出现了一个错误 - 加速响应滚动与传统滚动的区别。通过加速我的意思是文件在轨迹板上任意给定的移动量移动的距离 - 传统的滚动没有移动文件那么多,所以感觉迟钝。我报告了这个,似乎至少在10.14中得到了解决。
⑵尽管我可以从我的研究中得知,并且与Apple人交谈,“响应式滚动”旨在使滚动更加一致,即使应用程序占用主线程(通常会阻止事件流) - 它处理滚轮而不是在后台线程上的事件,然后用它们向主线程发送消息。因为这仍然涉及每个滚动事件调用的主线程(或滚动事件被合并)我不清楚这是什么情况这是一个胜利。可能有一些额外的魔术,其中scrollview将从缓存中绘制更多的文档你实现了可选的缓存内容。
在我的应用程序中,我实际上使用了带有虚拟(透明)文档的scrollview,我将其滚动事件和SceneKit相机移动。由于我在滚动时场景发生了巨大变化,因此尝试在可见矩形之外进行预渲染没有任何好处。
所以在我的情况下,我不再感觉到响应和传统滚动之间的任何性能差异(尽管我在提交错误时回复了)。