¿Cómo quita un CAEmitterLayer cuando finaliza la vida útil de sus CAEmitter Cells? En lugar de repetirlo hasta que lo elimine de la super capa

Estoy usando código genérico (de la demostración de iOS Fireworks) de una manera ligeramente cambiada. Tengo lo siguiente en una subclass de UIView. Lo que quiero es hacer que el fuego artificial aparezca en el punto que el usuario toca (no es difícil) y jugar durante toda la vida de CAEmitterLayer / CAEmitterCells. En cambio, esto se inicia de inmediato cuando lo agrego a addSublayer, como estoy seguro de que está destinado a hacerlo. Sin embargo, me gustaría usarlo de una manera ligeramente diferente. ¿Hay alguna forma de que pueda cambiar esto, así que hay una CATransaction con un bloque de finalización (para eliminar de SuperSuperlayer) o algo así? Cualquier idea es bienvenida.

#import "FireworksView.h" @implementation FireworksView - (void)launchFirework{ //Load the spark image for the particle CAEmitterLayer *mortor = [CAEmitterLayer layer]; mortor.emitterPosition = CGPointMake(self.bounds.size.width/2, self.bounds.size.height*(.75)); mortor.renderMode = kCAEmitterLayerAdditive; //Invisible particle representing the rocket before the explosion CAEmitterCell *rocket = [CAEmitterCell emitterCell]; rocket.emissionLongitude = -M_PI / 2; rocket.emissionLatitude = 0; rocket.lifetime = 1.6; rocket.birthRate = 1; rocket.velocity = 400; rocket.velocityRange = 100; rocket.yAcceleration = 250; rocket.emissionRange = M_PI / 4; rocket.color = CGColorCreateCopy([UIColor colorWithRed:.5 green:.5 blue:.5 alpha:.5].CGColor); rocket.networkingRange = 0.5; rocket.greenRange = 0.5; rocket.blueRange = 0.5; //Name the cell so that it can be animated later using keypath [rocket setName:@"rocket"]; //Flare particles emitted from the rocket as it flys CAEmitterCell *flare = [CAEmitterCell emitterCell]; flare.contents = (id)[UIImage imageNamed:@"tspark.png"].CGImage; flare.emissionLongitude = (4 * M_PI) / 2; flare.scale = 0.4; flare.velocity = 100; flare.birthRate = 45; flare.lifetime = 1.5; flare.yAcceleration = 350; flare.emissionRange = M_PI / 7; flare.alphaSpeed = -0.7; flare.scaleSpeed = -0.1; flare.scaleRange = 0.1; flare.beginTime = 0.01; flare.duration = 0.7; //The particles that make up the explosion CAEmitterCell *firework = [CAEmitterCell emitterCell]; firework.contents = (id)[UIImage imageNamed:@"tspark.png"].CGImage; firework.birthRate = 9999; firework.scale = 0.6; firework.velocity = 130; firework.lifetime = 2; firework.alphaSpeed = -0.2; firework.yAcceleration = 80; firework.beginTime = 1.5; firework.duration = 0.1; firework.emissionRange = 2 * M_PI; firework.scaleSpeed = -0.1; firework.spin = 2; //Name the cell so that it can be animated later using keypath [firework setName:@"firework"]; //preSpark is an invisible particle used to later emit the spark CAEmitterCell *preSpark = [CAEmitterCell emitterCell]; preSpark.birthRate = 80; preSpark.velocity = firework.velocity * 0.70; preSpark.lifetime = 1.7; preSpark.yAcceleration = firework.yAcceleration * 0.85; preSpark.beginTime = firework.beginTime - 0.2; preSpark.emissionRange = firework.emissionRange; preSpark.greenSpeed = 100; preSpark.blueSpeed = 100; preSpark.networkingSpeed = 100; //Name the cell so that it can be animated later using keypath [preSpark setName:@"preSpark"]; //The 'sparkle' at the end of a firework CAEmitterCell *spark = [CAEmitterCell emitterCell]; spark.contents = (id)[UIImage imageNamed:@"tspark.png"].CGImage; spark.lifetime = 0.05; spark.yAcceleration = 250; spark.beginTime = 0.8; spark.scale = 0.4; spark.birthRate = 10; preSpark.emitterCells = [NSArray arrayWithObjects:spark, nil]; rocket.emitterCells = [NSArray arrayWithObjects:flare, firework, preSpark, nil]; mortor.emitterCells = [NSArray arrayWithObjects:rocket, nil]; [self.layer addSublayer:mortor]; } 

La respuesta a esto es, usando CAEmitter, NO HAY MANERA – delegado, etc. – para detener al emisor cuando finaliza el ciclo. Lo único que puedes hacer es eliminarlo correctamente de la capa cuando creas que debería eliminarse.

Ok, así que pude lograr esto creando una animation con el delegado que disparó junto con el emisor. en animationDidStop, hice un bucle for que pasó por la jerarquía de mi vista y buscó emisores y los eliminó. Es un buggy y todavía quiero una solución real, pero esto funciona por ahora.

 for (CALayer *layer in _plusButton.layer.sublayers) { if (layer.class == [CAEmitterLayer class]) { [layer removeFromSuperlayer]; } }