Reputation: 253
I have setup and position the CAEmitterLayer. It shows images coming from the emitter.
The code works very well, but I have one problem. I would like to stop snowDribbbleBalls() function after 5 seconds it is called. I appreciate any help lead me to solve the problem.
(Instead of removing sublayers, I would like to simply stop function.)
//real code
class CompletedViewController: UIViewController {
self.snowDribbbleBalls()
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) { [weak self] in
cell.birthRate = 0
cell2.birthRate = 0
cell3.birthRate = 0
cell4.birthRate = 0
}
}
func snowDribbbleBalls() {
let emitter = Emitter.get(with: #imageLiteral(resourceName: "ichi"))
emitter.emitterPosition = CGPoint(x: view.frame.width / 2, y: 0)
emitter.emitterSize = CGSize(width: view.frame.width, height: 2)
self.view.layer.addSublayer(emitter)
let emitter2 = Emitter.get(with: #imageLiteral(resourceName: "ni"))
emitter2.emitterPosition = CGPoint(x: view.frame.width / 6, y: 0)
emitter2.emitterSize = CGSize(width: view.frame.width, height: 2)
self.view.layer.addSublayer(emitter2)
let emitter3 = Emitter.get(with: #imageLiteral(resourceName: "san"))
emitter3.emitterPosition = CGPoint(x: view.frame.width / 1, y: 0)
emitter3.emitterSize = CGSize(width: view.frame.width, height: 2)
self.view.layer.addSublayer(emitter3)
let emitter4 = Emitter.get(with: #imageLiteral(resourceName: "yon"))
emitter4.emitterPosition = CGPoint(x: view.frame.width / 3.5, y: 0)
emitter4.emitterSize = CGSize(width: view.frame.width, height: 2)
self.view.layer.addSublayer(emitter3)
}
class Emitter {
static func get(with image: UIImage) -> CAEmitterLayer {
let emitter = CAEmitterLayer()
emitter.emitterShape = kCAEmitterLayerLine
emitter.emitterCells = generateEmitterCells(with: image)
let emitter2 = CAEmitterLayer()
emitter2.emitterShape = kCAEmitterLayerLine
emitter2.emitterCells = generateEmitterCells(with: image)
let emitter3 = CAEmitterLayer()
emitter3.emitterShape = kCAEmitterLayerLine
emitter3.emitterCells = generateEmitterCells(with: image)
let emitter4 = CAEmitterLayer()
emitter4.emitterShape = kCAEmitterLayerLine
emitter4.emitterCells = generateEmitterCells(with: image)
return emitter
}
static func generateEmitterCells(with image: UIImage) -> [CAEmitterCell] {
var cells = [CAEmitterCell]()
let cell = CAEmitterCell()
cell.contents = image.cgImage
cell.birthRate = 30
cell.lifetime = 50
cell.velocity = CGFloat(300)
cell.emissionLongitude = (180 * (.pi/180))
cell.emissionRange = (14 * (.pi/180))
cell.scale = 0.25
cell.scaleRange = 0.3
////
let cell2 = CAEmitterCell()
cell2.contents = image.cgImage
cell2.birthRate = 26
cell2.lifetime = 50
cell2.velocity = CGFloat(160)
cell2.emissionLongitude = (180 * (.pi/180))
cell2.emissionRange = (12 * (.pi/180))
cell2.scale = 0.25
cell2.scaleRange = 0.2
////
let cell3 = CAEmitterCell()
cell3.contents = image.cgImage
cell3.birthRate = 20
cell3.lifetime = 50
cell3.velocity = CGFloat(160)
cell3.emissionLongitude = (180 * (.pi/180))
cell3.emissionRange = (16 * (.pi/180))
cell3.scale = 0.25
cell3.scaleRange = 0.2
////
let cell4 = CAEmitterCell()
cell4.contents = image.cgImage
cell4.birthRate = 27
cell4.lifetime = 20
cell4.velocity = CGFloat(260)
cell4.emissionLongitude = (180 * (.pi/180))
cell4.emissionRange = (10 * (.pi/180))
cell4.scale = 0.25
cell4.scaleRange = 0.2
cells.append(cell)
return cells
}
}
Upvotes: 0
Views: 397
Reputation: 35646
Just to make things clear... The function doesn't 'run' while the layer is emitting, so the real question is "How to stop the emitter ?" and the answer to this is by setting the birthRate
of the emitter layer to zero.
So just hold a reference (since you don't want to be removed) and set the birthRate
to zero after 5 seconds...
Something like:
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) { [weak self] in
// self.emitter is declared as
// var emitter: CAEmitterLayer!
// and set on `emitter = Emitter.get(with: #imageLiteral(resourceName: "ichi"))`
self?.emitter.birthRate = 0
}
Upvotes: 2