UICollectionView中的SKView性能差劲

3

将空的SKView添加到UICollectionView单元格上会使iPhone 6(iOS 9.x)上的滚动几乎不可能。假设集合视图包含6个项目,其中前3个是可见的,水平滚动下3个项目需要3秒钟并具有抖动。

以下是相关代码部分:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(ACDFilterCollectionViewCellConstants.CellIdentifier, forIndexPath: indexPath) as! ACDFilterCollectionViewCell

        let filterType = filters[indexPath.row]

        cell.titleLabel.text = filterType.rawValue

        let skview = SKView(frame: cell.frame)
        cell.filterView.addSubview(skview)

        return cell
    }

如何使我在UICollectionViewCells中使用SKViews时实现平滑滚动?

iOS 8.x版本中,当渲染此视图时会出现异常:

enter image description here


我仅使用SpriteKit来绘制带有自定义着色器的UIBezierPath,然后将其添加到我的UIView/UICollectionViewCell中。在单元格或在UICollectionView之外的其他视图中呈现形状看起来非常正常,直到我开始滚动。 - manikal
1
现在,除非我们获得更多信息,否则Caleb的答案是您可以得到的最好答案。您究竟想要实现什么?这些是否可以预先渲染并作为PNG添加到您的应用程序中,或者像Caleb所述的那样在屏幕外呈现并缓存? - DR Haus
我有点困惑,你说这是一个iOS 9的问题,但你提到在iOS 8上也会抛出异常。那么我理解这在iOS 8上也不起作用? - Skyler Lauren
@DRHaus 我正在尝试在iOS 8和iOS 9上使用SKView实现集合视图的平滑滚动。我曾经尝试过使用图像方法,只是出于好奇,但它并没有起作用,而且这也不是我想要的。我希望形状可以进行动画处理。 - manikal
@SkylerLauren 是的,它在iOS 8上无法工作,我正在问题截图中遇到异常。 - manikal
显示剩余2条评论
3个回答

4

我不知道性能差的具体原因,但我可以给你一些提示。

第一件要做的事情是对代码进行分析。使用Instruments来找出应用程序在滚动时花费时间最多的地方。是将SKView设置为它们进入屏幕时的昂贵部分吗?还是重复绘制所有这些精灵视图?是精灵视图里面的某些东西需要很长时间才能绘制完成吗?我听说SKShapeNode会拖慢性能。如果你从SKView中删除所有子节点会发生什么?

一旦你知道瓶颈在哪里,就可以决定如何继续。从你的评论中看来,你只是使用SKView来渲染一些路径,也许在绘制完成后它们不需要再次动画显示?如果是这样,也许你可以使用单个离屏SKView将你的路径渲染成一个图像,然后将该图像插入到集合单元格中。人们经常使用充满图片的集合,它们可以平稳滚动。


无论我是使用SKView SKShapeNode w/wo着色器,还是只是空的SKView,问题都是一样的。 我希望我的路径能一直动画,我尝试过异步生成并添加仅来自SKView的图像,使用drawViewHierarchyInRect,但这并没有帮助。 - manikal

3
我的初步建议是:降低你对框架交互和它们之间关系构建的期望。请查看CAShapeLayer,看看它是否可以完成你试图使用SKShapeNode和着色器实现的功能。CAShapeLayers有一个“shouldRasterize”功能,您可以应用Core Image过滤器等内容,这可能会使您接近所需的结果,而无需使用SKViews、SKShapeNode和SKShaders。
你所面临的问题是苹果新API和框架在质量和性能方面期望过高,以及它们之间的互动和包容能力。
这不是你的错。
苹果早就掌握了展示和销售技巧。
很长一段时间里,这些技巧只用于实体产品发布——推销人们购买的设备。
大约在已故伟大的乔布斯先生(愿他安息)病重和去世时,公司正在进行一个转型,积极推广快速开发和早期发布软件到应用商店。
其中大部分是为了对抗Android和谷歌。可能有一些共识(可能是公司现在领导的供应商关注渠道之间的共识),尽可能多地将应用程序放入商店是打败Android的方法。
为此,iOS 7被创建出来,包括UICollectionViews、AutoLayout和各种其他“神奇”的好东西,旨在消除大多数应用程序创建中设计和设计师的需要(和关注)。
这些设施给人留下了印象,认为API可以做任何事情,几乎不需要考虑设计,甚至不需要考虑技术设计。

所以开发人员进入框架时,他们充满希望、乐观地认为只要使用可用的框架和API,通过他们对WWDC视频和其他苹果推广材料的理解,就可以实现任何他们构思的东西。

不幸的是,上述的销售手法和表演意味着你认为可能的事情实际上仅限于你展示的字面演示。框架之间交织关系和成功的暗示和建议潜在功能仅仅是“可能的潜在未来功能”而已。

除了字面演示之外,几乎所有的东西都是有缺陷的,或者在某种程度上受到严重限制和性能不佳。在某些情况下,甚至展示的内容也会在后续出现故障或无法发布。

因此,如果您花时间想象像将SKView结合在UICollectionView中这样的事情,并认为这种关系应该可以工作,那么这个假设就是您的问题。

这个问题会变得更糟,当你开始考虑SKShapeNodes和Shaders时,它们在SceneKit中都有已知的问题。显然,你已经发现了问题所在,即UICollectionView中的SKViews性能不佳。这是第一个问题。你将在稍后从SKShapeNodes和着色器中获得更多的性能问题,然后SKShapeNode的不可变性也会成为你动画的问题。
这并不是一个错误的假设,你被引导相信框架的模块化是一件事,并且是iOS巨大框架的一个重要特性。
然而,这些都是早期的阶段,没有提到。Sprite Kit在iOS 9中基本上是有问题的,你可以在这里阅读更多关于其许多问题的信息:

https://forums.developer.apple.com/thread/14487

这里:

https://forums.developer.apple.com/thread/20758

这里:

https://forums.developer.apple.com/thread/17463

据我所知,尽管有关Scene Kit在iOS 9中的许多问题的噪音不断,但至今没有正式的沟通涉及这些问题的原因和/或性质。

其中一个困扰许多人的巨大问题是,在iOS 9中使用UIKit和SKViews(无论它们如何相互关联)会导致严重的性能问题。目前似乎除了将这两个框架分开之外,没有明显的解决方法。


我想我会尝试使用CAShapeLayer。CIFilters通常使用CIImage作为inputImage,如果我需要从CAShapeLayer创建CIImage,将其用作inputImage,然后将该过滤器添加到CAShapeLayer.filters中,这是没有意义的。 - manikal
是的,我知道你的意思。我们在一个插图应用程序中为图层制作了实时缩略图,并确保在用户可能与屏幕进行交互的时候不会发生各种事情,并采取各种技巧使事件序列以维持用户对性能的感知方式发生。 - Confused
这就是真正的诀窍。我们关注的是性能感知而不是实际性能,主要是因为要实现高性能、真正动态的更新是不可能的。这也是我所说的降低期望的意思。如果你能做到这一点,那么你就可以开始考虑如何呈现理想体验的hacky版本。 - Confused
只是确认一下,除了我上面描述的方法之外,没有其他将CIFilter应用于CAShapeLayer的方法吗?我该如何高效地将CAShapeLayer转换为CIImage? - manikal
我尝试使用renderInContext,但没有成功,也许我漏掉了什么:https://gist.github.com/manikal/00b54787701e389e648d - manikal
显示剩余6条评论

0

谢谢,Hal。它确实提高了性能,但还不太符合我的期望。 - manikal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接