Ios CAEmitterLayer未使用CACurrentMediaTime()正确计时,有时根本不显示

Ios CAEmitterLayer未使用CACurrentMediaTime()正确计时,有时根本不显示,ios,swift,caemitterlayer,caemittercell,Ios,Swift,Caemitterlayer,Caemittercell,我目前正在使用CAEmitterLayer制作一个粒子发射器,并在我启动动画时遇到了层预加载的问题,因此在我显示动画时,所有的粒子都会出现 许多答案都说罪魁祸首是CAEmitterLayer被预加载,我们只需在发射器上将其起始时间设置为CACurrentMediaTime() 见: 对我来说,这个解决方案不起作用,当在运行iOS 12.1的iPad Air设备上运行它时,发射器通常不会显示,有时会延迟显示 为了说明这个问题,我在github上做了一个项目: 这是主要代码,我有7个随机选择

我目前正在使用CAEmitterLayer制作一个粒子发射器,并在我启动动画时遇到了层预加载的问题,因此在我显示动画时,所有的粒子都会出现

许多答案都说罪魁祸首是CAEmitterLayer被预加载,我们只需在发射器上将其起始时间设置为CACurrentMediaTime()

见:

对我来说,这个解决方案不起作用,当在运行iOS 12.1的iPad Air设备上运行它时,发射器通常不会显示,有时会延迟显示

为了说明这个问题,我在github上做了一个项目:

这是主要代码,我有7个随机选择的粒子的不同图像和一个按钮,当按下时显示发射器

import UIKit

class ViewController: UIViewController {

    var particleImages = [UIImage]()
    var emitter: CAEmitterLayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        view.backgroundColor = UIColor.black

        // Populate the random images array for the particles
        for index in 1..<8 {
            if let image = UIImage(named: "StarParticle00\(index)") {
                particleImages.append(image)
            }

        }

        // Button pressed to make the emitter emit the particles
        let button = UIButton(frame: CGRect(x: view.frame.width * 0.5 - 60, y: view.frame.height * 0.5 - 40, width: 120, height: 80))
        button.setTitle("Emit!", for: .normal)
        button.setTitleColor(UIColor.white, for: .normal)
        button.backgroundColor = UIColor.blue
        button.addTarget(self, action: #selector(changeButton(sender:)), for: .touchDown)
        button.addTarget(self, action: #selector(addEmitter(sender:)), for: .touchUpInside)
        view.addSubview(button)

    }

    @objc func changeButton(sender: UIButton) {
        sender.alpha = 0.5
    }

    @objc func addEmitter(sender: UIButton) {

        sender.alpha = 1.0

        // IF an emitter already exists remove it.
        if emitter?.superlayer != nil {
            emitter?.removeFromSuperlayer()
        }

        emitter = CAEmitterLayer()
        emitter?.emitterShape = CAEmitterLayerEmitterShape.point
        emitter?.position = CGPoint(x: self.view.frame.width * 0.5, y: self.view.frame.height * 0.5)
        // So that the emitter starts now, and is not preloaded. 
        emitter?.beginTime = CACurrentMediaTime()

        var cells = [CAEmitterCell]()
        for _ in 0..<40 {
            let cell = CAEmitterCell()
            cell.birthRate = 1
            cell.lifetime = 3
            cell.lifetimeRange = 0.5
            cell.velocity = 500
            cell.velocityRange = 100
            cell.emissionRange = 2 * CGFloat(Double.pi)
            cell.contents = getRandomImage().cgImage
            cell.scale = 1
            cell.scaleRange = 0.5
            cells.append(cell)
        }

        emitter?.emitterCells = cells

        view.layer.addSublayer( emitter! )

    }

    func getRandomImage() -> UIImage {

        let upperBound = UInt32(particleImages.count)
        let randomIndex = Int(arc4random_uniform( upperBound ))

        return particleImages[randomIndex]
    }


}
导入UIKit
类ViewController:UIViewController{
var particleImages=[UIImage]()
var发射器:CAEmitterLayer?
重写func viewDidLoad(){
super.viewDidLoad()
//加载视图后,通常从nib执行任何其他设置。
view.backgroundColor=UIColor.black
//填充粒子的随机图像阵列

对于1中的索引,…我对核心动画有着丰富的经验,尽管我不得不承认CAEmitterLayer的经验不多。对于一个非常了解CALayer的人来说,一切看起来都很好,用CACurrentMediaTime()设置了开始时间有道理。但是,我运行了你的项目,发现它不起作用。对我来说,在单元格上设置起始时间达到了我预期的效果。
意思

//delay for 5.0 seconds
cell.beginTime = CACurrentMediaTime() + 5.0
cell.beginTime = CACurrentMediaTime() //immediate
cell.beginTime = CACurrentMediaTime() - 5.0 //5 seconds ago
整个文件

import UIKit

class ViewController: UIViewController {

    var particleImages = [UIImage]()
    var emitter: CAEmitterLayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        view.backgroundColor = UIColor.black

        // Populate the random images array for the particles
        for index in 1..<8 {
            if let image = UIImage(named: "StarParticle00\(index)") {
                particleImages.append(image)
            }

        }

        // Button pressed to make the emitter emit the particles
        let button = UIButton(frame: CGRect(x: view.frame.width * 0.5 - 60, y: view.frame.height * 0.5 - 40, width: 120, height: 80))
        button.setTitle("Emit!", for: .normal)
        button.setTitleColor(UIColor.white, for: .normal)
        button.backgroundColor = UIColor.blue
        button.addTarget(self, action: #selector(changeButton(sender:)), for: .touchDown)
        button.addTarget(self, action: #selector(addEmitter(sender:)), for: .touchUpInside)
        view.addSubview(button)

    }

    @objc func changeButton(sender: UIButton) {
        sender.alpha = 0.5
    }

    @objc func addEmitter(sender: UIButton) {

        sender.alpha = 1.0

        // IF an emitter already exists remove it.
        if emitter?.superlayer != nil {
            emitter?.removeFromSuperlayer()
        }

        emitter = CAEmitterLayer()
        emitter?.emitterShape = CAEmitterLayerEmitterShape.point
        emitter?.position = CGPoint(x: self.view.frame.width * 0.5, y: self.view.frame.height * 0.5)
        // So that the emitter starts now, and is not preloaded.
        var cells = [CAEmitterCell]()
        for _ in 0..<40 {
            let cell = CAEmitterCell()
            cell.birthRate = 1
            cell.lifetime = 3
            cell.lifetimeRange = 0.5
            cell.velocity = 500
            cell.velocityRange = 100
            cell.emissionRange = 2 * CGFloat(Double.pi)
            cell.contents = getRandomImage().cgImage
            cell.scale = 1
            cell.scaleRange = 0.5
            cell.beginTime = CACurrentMediaTime()
            cells.append(cell)
        }

        emitter?.emitterCells = cells
        view.layer.addSublayer( emitter! )
    }

    func getRandomImage() -> UIImage {

        let upperBound = UInt32(particleImages.count)
        let randomIndex = Int(arc4random_uniform( upperBound ))

        return particleImages[randomIndex]
    }


}
导入UIKit
类ViewController:UIViewController{
var particleImages=[UIImage]()
var发射器:CAEmitterLayer?
重写func viewDidLoad(){
super.viewDidLoad()
//加载视图后,通常从nib执行任何其他设置。
view.backgroundColor=UIColor.black
//填充粒子的随机图像阵列

对于1.中的索引,您完全正确,在单元格上设置CACurrentMediaTime()是有效的,我已在示例项目中进行了确认。尽管这是一种非常奇怪的行为,而且记录得非常糟糕。感谢您提供的解决方案,我非常感谢!