Search code examples
iosswiftuicaemitterlayeremitter

Adding different objects to CAEmitterLayer with forEach with SwiftUI


When I add more than one object, I have to write one by one as below. When I want to add 2 or more objects, I always have to copy and paste. I don't want that and I tried doing it with forLoop, but I only see whatever object was added last. enter image description here

ForLoop

I wrote a function. ForLoop works as much as the number of images in the array.

func prepareParticeCell(particles: [String]) -> CAEmitterCell {
    
    let particleCell = CAEmitterCell()
    
    for particleItem in particles {
        
        let particle = UIImage(named: particleItem)?.cgImage
        particleCell.contents = particle
        particleCell.name = "Square"
        particleCell.birthRate = 5
        particleCell.lifetime = 74.5
        particleCell.velocityRange = 0.0
        particleCell.velocity = 79.0
        particleCell.xAcceleration = 0.0
        particleCell.yAcceleration = 0.0
        particleCell.emissionLatitude = 1*6.0 * (.pi / 180)
        particleCell.emissionLongitude = -105.0 * (.pi / 180)
        particleCell.emissionRange = 360.0 * (.pi / 180.0)
        particleCell.spin = -65.6 * (.pi / 180.0)
        particleCell.spinRange = 314.2 * (.pi / 180.0)
        particleCell.scale = 0.043
        particleCell.scaleRange = 0.7
        particleCell.scaleSpeed = 0.02
        particleCell.alphaRange = 0.0
        particleCell.alphaSpeed = 0.47
        particleCell.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor
    }
    return particleCell
}

Using Function

 let host = UIView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
        
        let particlesLayer = CAEmitterLayer()
        particlesLayer.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        host.layer.insertSublayer(particlesLayer, at: 0)
        host.layer.masksToBounds = true
        host.insetsLayoutMarginsFromSafeArea = false
        particlesLayer.backgroundColor = .none
        particlesLayer.emitterShape = .circle
        particlesLayer.emitterPosition = CGPoint(x: 509.4, y: 707.7)
        particlesLayer.emitterSize = CGSize(width: 1648.0, height: 1112.0)
        particlesLayer.emitterMode = .outline
        particlesLayer.renderMode = .backToFront
        
        particlesLayer.emitterCells = [prepareParticeCell(particles: particleImages)] // here
        return host

Solution

  • You have to return an array, I gave you 2 way for this issue, one with for another with map. Both working the same thing.


    func prepareParticeCellV1(particles: [String]) -> [CAEmitterCell] {
        
        var arrayParticleCell: [CAEmitterCell] = [CAEmitterCell]()  // <<: Here
        
        for particleItem in particles {
            
            let particleCell: CAEmitterCell = CAEmitterCell()
            
            particleCell.contents = UIImage(named: particleItem)?.cgImage
            particleCell.name = "Square"
            particleCell.birthRate = 5
            particleCell.lifetime = 74.5
            particleCell.velocityRange = 0.0
            particleCell.velocity = 79.0
            particleCell.xAcceleration = 0.0
            particleCell.yAcceleration = 0.0
            particleCell.emissionLatitude = 1*6.0 * (.pi / 180)
            particleCell.emissionLongitude = -105.0 * (.pi / 180)
            particleCell.emissionRange = 360.0 * (.pi / 180.0)
            particleCell.spin = -65.6 * (.pi / 180.0)
            particleCell.spinRange = 314.2 * (.pi / 180.0)
            particleCell.scale = 0.043
            particleCell.scaleRange = 0.7
            particleCell.scaleSpeed = 0.02
            particleCell.alphaRange = 0.0
            particleCell.alphaSpeed = 0.47
            particleCell.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor
            
            arrayParticleCell.append(particleCell)
    
        }
    
        return arrayParticleCell
    }
    

    func prepareParticeCellV2(particles: [String]) -> [CAEmitterCell] {
        
        return particles.map({ item in
            
            let particleCell: CAEmitterCell = CAEmitterCell()
            
            particleCell.contents = UIImage(named: item)?.cgImage
            particleCell.name = "Square"
            particleCell.birthRate = 5
            particleCell.lifetime = 74.5
            particleCell.velocityRange = 0.0
            particleCell.velocity = 79.0
            particleCell.xAcceleration = 0.0
            particleCell.yAcceleration = 0.0
            particleCell.emissionLatitude = 1*6.0 * (.pi / 180)
            particleCell.emissionLongitude = -105.0 * (.pi / 180)
            particleCell.emissionRange = 360.0 * (.pi / 180.0)
            particleCell.spin = -65.6 * (.pi / 180.0)
            particleCell.spinRange = 314.2 * (.pi / 180.0)
            particleCell.scale = 0.043
            particleCell.scaleRange = 0.7
            particleCell.scaleSpeed = 0.02
            particleCell.alphaRange = 0.0
            particleCell.alphaSpeed = 0.47
            particleCell.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor
            
            return particleCell
            
        })
        
    }