0

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 } } 
4
  • DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { self.snowDribbbleBalls() }) if you want to remove this than use removefrom subview Commented Jul 17, 2017 at 6:37
  • snowDribbbleBalls() will run just a few microseconds, no seconds. In fact do you want stop an animation? Commented Jul 17, 2017 at 6:37
  • @ macmoonshine yes I would like to stop animation! Commented Jul 17, 2017 at 6:42
  • You can use this answer stackoverflow.com/a/25120393/2000162 Run with a delay and cancel whenever you need it Commented Jul 17, 2017 at 6:55

1 Answer 1

2

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 } 
Sign up to request clarification or add additional context in comments.

6 Comments

@risa8 Can you please edit your question and share your code? Because I did try my answer before posting and is working fine...
Ok give me a second. The error is "Value of CompleteViewController has no member cell2."
... so what is cell2? It seems that this problem is unrelated to the specific question...
Sorry mistype it is cell
I would gladly help you with that, but you have to post some real code in your question. Just hit Edit and include the code as it is now if possible
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.