swift - 使用 CAShapeLayers 进行 mask 的动画和滚动性能严重滞后

标签 swift uiscrollview calayer animatewithduration rasterizing

我问这个问题是不得已的方法,因为我发现并尝试过的任何解决方案都没有产生积极的结果。我正在设计一个应用程序,用户可以在其中操作 UIView 并制作由 UIBezierPath 定义的自定义形状。没有过多的细节,为了避免让您感到无聊,这基本上就是发生的事情:

override func drawRect(rect: CGRect) {

    // Create the path
    var path = UIBezierPath()

    // ...... The path is defined, set to be drawn in the view's frame

    // Draw the stroke of the actual path, close it and clip.
    path.lineWidth = 2.0
    UIColor.whiteColor().setStroke()
    path.stroke()
    path.closePath()
    path.addClip()

    // Create a CAShapeLayer to crop everything outside the path
    let maskForPath = CAShapeLayer()
    maskForPath.path = path.CGPath
    self.layer.mask = maskForPath
}

这样效果很好,随着用户继续使用该应用程序,他们会创建越来越多的形状,并且他们之前创建的形状会存储​​在 UIScrollView 中,供他们稍后查看、选择和编辑在。无论如何,一旦创建了多个形状(比如 15 个或更多),我使用 UIView.animateWithDuration 执行的任何动画都会变得非常不稳定,UIScrollView 内的滚动也是如此>。这是令人沮丧的,因为在创建大量 View 之前,一切都很好并且很流畅。此外,我尝试使用 touchesBegantouchesMoved 手动移动 View ,当我以这种方式移动 View 时,它们移动得很好,没有延迟或任何东西。

到目前为止,我已经用尽了我能找到的所有解决方案。以下是我到目前为止尝试过的一些事情:

1) 一)layer.shouldRasterize = true

b) layer.rasterizationScale = UIScreen.mainScreen().scale

2) layer.drawsAsynchronously = true

3) AsyncDisplayKit

4) layer.allowsEdgeAntialiasing = true

这些解决方案都没有产生积极的结果。谁能想到我可能遗漏的任何东西,或者有解决这个问题的想法?这似乎不是内存问题,因为即使我在 UIScrollView 中嵌套了很多这些 View ,我的应用程序平均也只使用 30mb 内存。此外,CPU 的影响似乎很小。我没有使用任何阴影,我已经尝试在 iPhone 5s、6 和 6s Plus 上进行测试,结果都相同,所以这似乎不是设备的问题。希望有人能帮我找到解决方案,因为它让应用程序看起来像垃圾,而且据我所知,系统甚至没有被征税。

感谢您的帮助!提前致谢!

最佳答案

drawRect 有时会拖累性能。

因此,我建议使用 CAShapeLayer 来绘制路径。

您可能想要为此创建一个新的形状层,因为您已经在使用当前的形状层进行 mask 。您需要设置 strokeColorlineWidth在它上面 - 以及设置 fillColor clearColor 如果您只是想要描边(而不是填充)。

然后您可以删除您的绘图代码 - 因此完全删除 drawRect(这应该会立即提升性能,因为 UIView 必须为自定义绘图)。您还应该发现,您为优化它而尝试执行的所有上述操作应该会更好地工作。

与 Core Graphics 绘图不同,Core Animation 能够利用 GPU - 因此通常在性能方面表现更好。

您还可以通过消除图层蒙版来显着提高您的性能。如果您的 View 仅具有纯色背景色 - 您可以简单地在笔画形状图层上设置 fillColor 来实现这一点,并放弃 mask 。

此外,正如一些相关答案所说,在多个子层上将 shouldRasterize 设置为 true 时有时会出现问题。您应该只在单个超层上将其设置为 true

另一个提高性能的潜在想法是将所有 View 合并到一个 View 中 - 并将您的路径合并到一个由子路径组成的单个路径中。然后,您可以使用 mask 和描边层显示此路径。

关于swift - 使用 CAShapeLayers 进行 mask 的动画和滚动性能严重滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36378427/

相关文章:

ios - 在我的项目中安装 LayerKit 时出现问题

Swift UIWebView 约束全屏

ios - viewDidAppear 延迟 0.5 秒

ios - 如何识别特定图像在 imageview 动画期间正在动画?

ios - UITableViewCell 上的循环 UIImageView 在第一次加载时不起作用

ios - 如何将圆形蒙版应用到 UIImageView

ios - 如何将图像从 tableView 传输到另一个 imageViewController?

iOS AutoLayout 自动调整整个表格(不是单元格!)高度

iphone - UIWebView 嵌入 UIScrollView 时不滚动

uiscrollview - Xcode 5 iOS 7 - UIScrollView 行为异常