CAEmitterLayer 最终在添加 EmitterCells 时有延迟

CAEmitterLayer, eventually, has delay when adding EmitterCells

我们一直看到的一个非常奇怪的问题(下面的 gif),

  1. 我们有一个视图控制器,它有一个 TeamBadgeView, 这是一个发出表情符号的按钮 CAEmitterCells
  2. 点击此按钮可让用户在屏幕上发送垃圾表情符号
  3. 正在关闭呈现的视图控制器,并重新呈现视图控制器,现在有延迟。我 present/dismiss 视图控制器的次数越多,CAEmitterCell 变得越来越无响应
  4. 已确认这不是泄漏问题,正在正确释放视图控制器和按钮
  5. 我试过移动 CAEmitterLayerCAEmitterCell,在按钮中保留引用,并在本地声明,但类似的问题
  6. 也许最奇怪的是,如果我根本不按按钮,只是 present/dismiss 多次 viewcontroller,然后再按按钮,就会出现延迟。唯一没有延迟的是在第一次显示视图控制器时按下按钮
  7. 我已经确认按钮的 action 被正确触发,每次我向按钮发送垃圾邮件。只是发射器单元有几秒钟没有渲染。还有一些发射器单元根本不渲染

已经到了令人难以置信的地步,有人对这可能是什么有任何想法或线索吗?

ViewController 的首次展示:

第 5 次呈现 ViewController 后(以相同的速度按下按钮):

ViewController代码:

let teamBadgeView = TeamBadgeView.fromNib()
teamBadgeView.configure()

按钮代码:

class TeamBadgeView: UIView {
    let emitter = CAEmitterLayer()
    let fireSize = CGSize(width: 16, height: 18)
    let fireScale: CGFloat = 0.8

    func configure() {
        emitter.seed = UInt32(CACurrentMediaTime())
        emitter.emitterPosition = CGPoint(x: bounds.midX, y: 0)
        emitter.emitterShape = CAEmitterLayerEmitterShape.line
        emitter.emitterSize = fireSize
        emitter.renderMode = CAEmitterLayerRenderMode.additive
        layer.addSublayer(emitter)
    }

    @IBAction func tapAction(_ sender: Any) {
        emitFire()
    }

    private func emitFire() {
        let cell = CAEmitterCell()
        let beginTime = CACurrentMediaTime()
        cell.birthRate = 1
        cell.beginTime = beginTime
        cell.duration = 1
        cell.lifetime = 1
        cell.velocity = 250
        cell.velocityRange = 50
        cell.yAcceleration = 100
        cell.alphaSpeed = -1.5
        cell.scale = fireScale
        cell.emissionRange = .pi/8
        cell.contents = NSAttributedString(string: "").toImage(size: fireSize)?.cgImage

        emitter.emitterCells = [cell]
    }
}

而不是每次都设置emitterCells数组:

emitter.emitterCells = [cell]

...将新单元格附加到它。如果它为 nil,请确保将其初始化为空数组,否则追加将不起作用:

if emitter.emitterCells == nil {
    emitter.emitterCells = []
}

emitter.emitterCells?.append(cell)

多亏了@TylerTheCompiler,我们才能够解决这个问题,这真的很蹩脚。

一行更改,而不是设置 emitterCells,我们需要附加

    emitter.emitterCells = [cell]

成为

    emitter.emitterCells?.append(cell)

我们之所以没有注意到这一点,是因为它似乎与英雄转换有一种奇怪的互动。我们的 ViewController 是通过 Hero Transition 呈现的,由于某种原因,它第一次呈现时,emitterCells = [cell] 会按预期工作......但由于某种原因,对于每个后续的 Hero Transition 到 ViewController,细胞开始发射越来越慢,直到它回到预期的缓慢状态。莫名其妙,可能是Hero的bug,谁知道呢