iOS Core Animation: CALayer bringSublayerToFront?

¿Cómo traigo una CALayer sublayer al frente de todas las subcapas, análoga a -[UIView bringSubviewToFront] ?

Esta es la variación de la implementación de @ MattDiPasquale que refleja la lógica de UIView con mayor precisión:

 - (void) bringSublayerToFront:(CALayer *)layer { [layer removeFromSuperlayer]; [self insertSublayer:layer atIndex:[self.sublayers count]]; } - (void) sendSublayerToBack:(CALayer *)layer { [layer removeFromSuperlayer]; [self insertSublayer:layer atIndex:0]; } 

Nota : si no utiliza ARC, es posible que desee agregar [layer retain] en la parte superior y [layer release] en la parte inferior de ambas funciones para asegurarse de que la layer no se destruya accidentalmente en el caso de que retenga count = 1.

Tengo curiosidad por qué ninguna de estas respuestas menciona el atributo zPosition en CALayer. Core Animation mira este atributo para descubrir el order de representación de capas. Cuanto mayor sea el valor, más cerca estará del frente. Estas respuestas funcionan siempre y cuando su position z sea 0, pero para llevar fácilmente una capa al frente, establezca su valor de zPosition más alto que el rest de las subcapas.

Código derecho aquí

 - (void)bringSublayerToFront:(CALayer *)layer { CALayer *superlayer = layer.superlayer; [layer removeFromSuperlayer]; [superlayer insertSublayer:layer atIndex:[superlayer.sublayers count]]; } - (void)sendSublayerToBack:(CALayer *)layer { CALayer *superlayer = layer.superlayer; [layer removeFromSuperlayer]; [superlayer insertSublayer:layer atIndex:0]; } 

Este es el código correcto:

 -(void)bringSubLayerToFront:(CALayer*)layer { [layer.superLayer addSubLayer:layer]; } -(void)sendSubLayerToBack:(CALayer*)layer { [layer.superlayer insertSublayer:layer atIndex:0]; } 

Puede implementar esta funcionalidad en una categoría en CALayer así:

CALayer + Extension.h

 #import <QuartzCore/QuartzCore.h> typedef void (^ActionsBlock)(void); @interface CALayer (Extension) + (void)performWithoutAnimation:(ActionsBlock)actionsWithoutAnimation; - (void)bringSublayerToFront:(CALayer *)layer; @end 

CALayer + Extension.m

 #import "CALayer+Extension.h" @implementation CALayer (Extension) + (void)performWithoutAnimation:(ActionsBlock)actionsWithoutAnimation { if (actionsWithoutAnimation) { // Wrap actions in a transaction block to avoid implicit animations. [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; actionsWithoutAnimation(); [CATransaction commit]; } } - (void)bringSublayerToFront:(CALayer *)layer { // Bring to front only if already in this layer's hierarchy. if ([layer superlayer] == self) { [CALayer performWithoutAnimation:^{ // Add 'layer' to the end of the receiver's sublayers array. // If 'layer' already has a superlayer, it will be removed before being added. [self addSublayer:layer]; }]; } } @end 

Y para un acceso fácil, puede #import "CALayer+Extension.h" en el file Prefix.pch (encabezado precomstackdo) de su proyecto.

Cree una categoría de CALayer como esta:

 @interface CALayer (Utils) - (void)bringSublayerToFront; @end @implementation CALayer (Utils) - (void)bringSublayerToFront { CGFloat maxZPosition = 0; // The higher the value, the closer it is to the front. By default is 0. for (CALayer *layer in self.superlayer.sublayers) { maxZPosition = (layer.zPosition > maxZPosition) ? layer.zPosition : maxZPosition; } self.zPosition = maxZPosition + 1; } @end 

No creo que existan tales methods, pero es fácil cambiarlos.

 // CALayer+Additions.h @interface CALayer (Additions) - (void)bringSublayerToFront:(CALayer *)layer; - (void)sendSublayerToBack:(CALayer *)layer; @end // CALayer+Additions.m @implementation CALayer (Additions) - (void)bringSublayerToFront:(CALayer *)layer { CALayer *superlayer = self.superlayer; [self removeFromSuperlayer]; [superlayer insertSublayer:gradientLayer atIndex:[self.sublayers count]-1]; } - (void)sendSublayerToBack:(CALayer *)layer { CALayer *superlayer = self.superlayer; [self removeFromSuperlayer]; [superlayer insertSublayer:gradientLayer atIndex:0]; }