【问题标题】:In SwiftUI, how to draw shadows with high performance?在 SwiftUI 中,如何高性能绘制阴影?
【发布时间】:2021-01-12 14:10:22
【问题描述】:

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

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

【问题讨论】:

  • 你能展示你的代码或如何重现这个的例子吗?

标签: swift swiftui shadow


【解决方案1】:

这个警告并不是因为你的代码本身就不好,而是为了告诉你有更多的表现阴影的方法。

由于当前编写的 UI 元素,SwiftUI 会根据视图对象当时的位置和边界动态地(在运行时)在视图对象周围绘制阴影,并且该渲染将在视图的整个生命周期中跟随视图。

这是一个数学密集型过程,在最好的情况下涉及对 GPU 的许多绘制调用,在最坏的情况下也会出现 CPU 瓶颈。

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

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


选项 1

如果您只是想让错误消失,最简单的做法是通过添加强制对视图 + 阴影进行 GPU 调用光栅化

.drawingGroup()

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


选项 2

说到 UIKit,另一种选择是去那里使用 SwiftUI 绘图逻辑的 UIViewRepresentable 或完全独立的 UIView。无论哪种方式:

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

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


选项 3

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

当游戏开发者拥有糟糕的硬件但仍然希望事情看起来不错时,这就是他们过去常常做的那种骇人听闻的工作。


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

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

【讨论】:

  • 使用 .drawingGroup() 启动 RAM 使用量!至少在包含大量图像的列表中的视图上。不知道为什么。似乎光栅化的视图被保存在内存中。
  • 是的,.drawingGroup() 就像 layer.shouldRasterize 一样,会将您的所有视图放入 RAM 以便以后快速访问。这有点像光栅化的定义......它的初始设置时间要慢得多,因为它必须将图像加载到 RAM 中......但是它可以更快地动画和移动项目,因为它不必重新计算每一帧的绘图,它只是在内存中抓取它。一切都是权衡……懒惰/易于实现 vs 高性能结果 vs 适应性 vs 二进制大小。做出好的选择。 ;)
猜你喜欢
  • 2016-04-15
  • 1970-01-01
  • 2010-11-16
  • 2010-10-22
  • 1970-01-01
  • 2021-02-11
  • 2012-02-16
  • 1970-01-01
相关资源
最近更新 更多