NSScrollView:使用CMD +滚动交互放大并保留响应式滚动

时间:2017-10-17 08:16:40

标签: objective-c cocoa appkit nsscrollview nsevent

在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 个答案:

答案 0 :(得分:0)

因为我有更多数据,所以我将在这里回答,而不是发表评论。

“响应式滚动”有两个问题:

(1)几年前,出现了一个错误-响应式加速与传统滚动的加速方式有所不同。加速是指文件在触控板上进行任何给定的手指移动量时行进的距离-传统滚动不会移动文件太多,因此感觉很慢。我报告了这个问题,至少似乎已经在10.14中修复了。

⑵从我的研究和与Apple人士的交谈中我可以看出,“响应式滚动”旨在使滚动更加一致,即使应用程序占用了主线程(通常会阻止事件流)也是如此。而是在后台线程上处理滚轮事件,然后向它们发送消息给主线程。由于这仍涉及每个滚动事件(或合并的滚动事件)被调用的主线程,所以我不清楚这在哪种情况下是成功的。滚动视图将从缓存中提取更多文档可能还有些神奇您的内容将实现可选的缓存内容。

在我的应用程序中,我实际上是使用带有虚拟(透明)文档的滚动视图,并获取其滚动事件并在SceneKit摄像机周围移动。由于在滚动时我的场景发生了巨大变化,因此尝试在可见矩形外部进行预渲染没有任何好处。

因此,就我而言,我不再感觉到响应式滚动和旧式滚动之间的性能差异(尽管我在提交错误时回过头来)。

相关问题