Layer-backed NSTextView(drawsBackground为false)闲置时大量额外绘图问题咨询
这确实是AppKit里一个有点反直觉的细节,我之前排查类似问题时也踩过这个坑,给你拆解下背后的逻辑:
Layer-backed模式下的裁剪缺失问题
当你把wantsLayer设为true同时drawsBackground设为false时,NSTextView的渲染上下文会切换到基于CALayer的模式,但因为没有开启背景绘制,系统不会为文本视图的层创建一个用于裁剪的不透明背景容器。这就导致NSLayoutManager在响应光标闪烁的绘制请求时,无法确定哪些文本区域是可见的——它没有明确的裁剪边界来限制工作范围,所以会遍历并处理整个NSTextStorage里的所有文本,哪怕是屏幕外完全不可见的部分,这就是CPU负载飙升的核心原因。正常场景的优化逻辑
当drawsBackground=true或者wantsLayer=false时,系统会自动提供明确的裁剪机制:要么是视图背景带来的绘制裁剪,要么是传统AppKit视图的可见区域裁剪。这时NSLayoutManager只会针对当前可见的文本区域做布局和绘制,光标闪烁触发的工作量就非常小,CPU占用自然就降下来了。为什么重写
shouldDrawInsertionPoint能解决问题
这个方法返回false时,直接跳过了插入点(光标)的绘制触发逻辑,那一轮不必要的全文本布局和绘制请求也就不会被发起,所以CPU负载会直接降为0,但代价是看不到光标了,这显然不是长久之计。
额外的优化建议
如果不想开启背景绘制,除了设置drawsBackground=true之外,还可以尝试给文本视图的layer手动添加一个背景色(哪怕是[NSColor clearColor]),同时确保layer的masksToBounds设为true——这样就能给NSLayoutManager提供明确的裁剪边界,让它只处理可见区域的内容,既能保持无背景的视觉效果,又能避免过量绘图。
内容的提问来源于stack exchange,提问作者Mattie

