在单个操作中更新多个NSTextView对象的内容

时间:2018-05-29 23:03:10

标签: cocoa appkit

我正在处理的数据库应用程序可以有一个窗口,其中包含多个NSTextView元素,用于显示和编辑数据。当重新定位数据库中的当前位置时,窗口中的所有NSTextView对象都需要使用新内容进行更新。这是通过一个循环来完成的,该循环扫描每个对象并检查是否需要更新。如果是,则计算新值,然后使用[NSTextView setString:]方法进行更新。这是所涉及代码的简化版本。

for formObject in formObjectsInWindow {
    NSTextView * objectTextView = [formObject textView];
    NSString * updatedValue = [formObject calculateValue];
    [objectTextView setString: updatedValue];
}

这样可行,但是如果有很多对象,它会有点慢。可能相关,显示器不会一次全部更新,你可以在对象更新时实际看到“波纹”,如本电影所示(此电影速度已降至1/4速度,使涟漪效果更加明显,但它绝对可以全速显示。)

enter image description here

如果你已经走到这一步,你可能会怀疑calculateValue方法很慢,但这不是问题。在其他地方使用相同的代码并以每秒数万次的操作运行。此外,此延迟仅在更新操作期间发生,当首次打开窗口时不会发生此延迟,即使此时需要相同的计算。这是一个例子。请注意,当我切换回详细视图时,即使记录已更改且所有值都不同,所有NSTextView对象也会立即更新。

enter image description here

我怀疑[NSTextView setString:]方法正在更新屏幕外缓冲区,然后立即将其复制到屏幕缓冲区,以便对每个项目反复进行这种双重缓冲,从而导致延迟和波纹。如果是这样,我肯定必须有某种方法来防止这种情况,以便屏幕只在更新所有值后才更新。这可能是我想念的简单事情,但我担心我应该怎么做。

顺便说一下,这个应用程序不使用图层支持的视图,也没有与QuartzCore框架链接。

1 个答案:

答案 0 :(得分:0)

我在WWDC 2018实验室与Apple工程师提出了这个问题。事实证明,问题在于setString:方法没有将NSTextView对象标记为需要显示。系统最终确实会注意到文本已更改并更新了显示,但这是在异步过程中发生的,因此会产生“波纹”效果。因此,解决方法只是在调用setNeedsDisplay之后向setString添加调用。

[objectTextView setString: updatedValue]
[objectTextView setNeedsDisplay:YES];

添加这一行代码可解决此问题,不再产生连锁反应。

有人告诉我这实际上是一个错误,因此希望以后的macOS版本中不需要此额外的行。根据要求,已提交了雷达文件(如果有任何Apple工程师正在阅读此文件,则为41273611)。