我有一个有趣的案例。 并且需要帮助。
我的Mac应用程序具有一个层托管的NSView,其中包含许多层,子层和子子层。想象一下一个带有项目(图标,文本标签)的Finder窗口……类似的东西。每个项目都有一个按钮,即选择背景层。
一切都很好,直到您拥有1000个这些物品为止。
现在有了很多这些项目,当我尝试与此 View 进行交互时,我的应用程序将无响应。而且棘手的是,不是我的应用消耗了CPU,而是WindowServer。达到100%,系统卡住了一段时间。
重要说明:
我的观点是应用界面的一部分。有一个带有其他 View 的主窗口。他们也有自己的结构。
而且我注意到,如果将这个层托管的 View 放到一个单独的窗口中,它可以很好地工作,并且不会卡住具有相同1000个项目的对象。但是,如果我将其放回主窗口,它将开始停止系统。
问题
我已经进行了一些测试,并删除了每个项目的所有子层,而每个仅剩下一两个。它减少了系统的负载,但仍然很糟糕。我已经禁用了所有图纸-只是图标的小图像。也没有帮助。
最佳答案
WindowServer
的主要工作是为macOS绘制与图形相关的事物,这意味着您可以从整个屏幕上看到所有内容,您必须仔细阅读WindowServer
并为您绘制图形。
WindowServer使用高CPU的原因很多。
在看到确切的代码之前,我无法告诉您为什么将元素放在单独的窗口中可以有所帮助。也许窗口本身隐藏了一些东西以便于绘制?
我的一款软件具有很多图形元素和动画。但是我从来没有遇到过你的问题。如何创建一个测试项目并尝试类似的事情?有时,这有助于在更清晰的项目结构上发现问题。
我创建了一个简单的演示,该演示在窗口中具有100 * 100个子层。似乎一点问题都没有。
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
self.window.contentView?.wantsLayer = true
let size = 10
for i in 0..<10000 {
let x = i%100
let y = i/100
let layer = CALayer()
layer.frame = NSRect(x: x*size, y: y*size, width: size, height: size)
layer.backgroundColor = .random()
self.window.contentView?.layer?.addSublayer(layer)
}
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
extension CGFloat {
static func random() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}
}
extension CGColor {
static func random() -> CGColor {
return CGColor(red: .random(),
green: .random(),
blue: .random(),
alpha: 1.0)
}
}