SwiftUI 中,如何绘制高性能的阴影?

In SwiftUI, how to draw shadows with high performance?

我使用 .shadow(color:, radius:, x:, y:) 在我的应用程序中绘制阴影。这是我所知道的在 SwiftUI 中绘制应用程序的唯一方法。我使用 .sheet(isPresented:, content:) 方法弹出一个视图,其中包含很多阴影,当我调试视图层次结构时,我看到了这些警告:

但我不知道如何设置shadowPath,或者在SwiftUI中将阴影预渲染成图像并将其放在图层下,请帮助我。

出现这个警告并不是因为您的代码本身就很糟糕,而是告诉您还有更高效的阴影渲染方法。

由于您的 UI 元素当前已写入,SwiftUI 正在根据视图对象的位置和边界在时间,并且该渲染将在其整个生命周期中跟随视图。

这是一个数学密集型过程,最好的情况下涉及 GPU 的许多 draw-calls,最坏的情况下 CPU 瓶颈。

Swift 中有几种不同的渲染阴影的方法。他们中的大多数使用 SwiftUI 之外的框架(UIKit 和 CoreGraphics,通常,尽管 Metal、Core Animation 和 Core Image 在各种应用程序中都很重要。)

如果您在目标硬件上的 UI 层中没有看到性能问题,则此警告可能不是什么大问题,但如果您非常有动力解决问题,则有一些选择:


选项 1

如果您只是想让错误消失,最简单的方法就是通过添加

强制对视图 + 阴影进行 GPU 调用光栅化
.drawingGroup()

.shadow 视图之后的某处。请注意,与动态阴影相比,这可能看起来像废话。如果您熟悉 UIKit,这类似于 UIView 上的 layer.shouldRasterize 属性。


选项 2

说到 UIKit,另一种方法是前往那里并使用 SwiftUI 绘图逻辑的 UIViewRepresentable,或者完全单独 UI 查看。无论哪种方式:

myView = UIView()
myView.layer.shadowPath = UIBezierPath(rect: myView.bounds.cgPath)

应该让你开始......其他影子属性和东西会有所帮助。


选项 3

您可以通过编程方式(困难)或在图像编辑应用程序中(烦人)将阴影渲染为图像,加载为 Z 索引低于视图的图像,并缩放它们以产生错觉深度。

这是游戏开发人员过去常常在硬件糟糕但仍希望游戏看起来不错时所做的那种骇人听闻的工作。


最终...对于大多数 SwiftUI 次观看,此警告可能会被忽略。如果您在 Instruments 中加载代码,您可能会发现视图下阴影的动态渲染可能不会显着影响您的视图渲染性能。此警告通常仅在 UI 调试会话中可见。

希望这有助于您找到解决方案。