Sí, sí hay ...
Si desea que un radio de esquina y una gota de sombra, no se presenta en - masksToBounds, sino más bien establecer el radio de la esquina y establecer el camino de bezier de la sombra con un rect redondeado. Mantener el radio de los dos el mismo:
[layer setShadowOffset:CGSizeMake(0, 3)];
[layer setShadowOpacity:0.4];
[layer setShadowRadius:3.0f];
[layer setShouldRasterize:YES];
[layer setCornerRadius:12.0f];
[layer setShadowPath:
[[UIBezierPath bezierPathWithRoundedRect:[self bounds]
cornerRadius:12.0f] CGPath]];
Es posible que desee comprobar su rendimiento sin el parámetro -shouldRasterize establecer una vez que se está configurando la ruta de sombra. El rendimiento del dibujo tiende a ser muy bueno una vez que ha establecido una ruta de sombra.
ACTUALIZACIÓN
no había mirado a este problema en un cierto tiempo, pero parece que ya no es necesario fijar un shadowPath
con el fin de conseguir que esto funcione. Simplemente configurando cornerRadius
y shadowOpacity
funcionará ahora. Creo que este ha sido el caso desde iOS5 (por lo que puedo ver). Proporcionar esta actualización probablemente sea innecesario, ya que la configuración de esos parámetros 'simplemente funciona', pero lo proporcionaré para la posteridad. En resumen, esto es ahora todo lo que necesita:
[layer setShadowOpacity:0.4];
[layer setCornerRadius:12.0f];
Si aún necesita un mejor rendimiento, puede seguir adelante y establecer el parámetro shouldRasterize
así:
[layer setShouldRasterize:YES];
Y hablando de rendimiento, que vale la pena teniendo en cuenta que si está notando animaciones lentas, querrá usar la técnica de establecer la ruta de sombra después de todo. Esta actualización fue solo para señalar que ya no es necesario establecer la ruta para lograr el efecto de mostrar tanto un radio de esquina como una sombra al mismo tiempo. Sin embargo, si el rendimiento es su prioridad, use una ruta.
ACTUALIZACIÓN 2
Dado que las personas parecen estar teniendo problemas para conseguir que esto funcione en algunos casos, voy a publicar un fragmento de código más completa aquí de un proyecto de ejemplo que he creado:
- (void)viewDidLoad
{
[super viewDidLoad];
CALayer *layer = [CALayer layer];
[layer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 200.0f)];
[layer setPosition:[[self view] center]];
[layer setBackgroundColor:[[UIColor lightGrayColor] CGColor]];
[layer setShadowOpacity:0.55f];
[layer setCornerRadius:8.0f];
[layer setBorderWidth:1.0f];
[[[self view] layer] addSublayer:layer];
[[[self testView] layer] setShadowOpacity:0.55f];
[[[self testView] layer] setShadowRadius:15.0f];
[[[self testView] layer] setCornerRadius:8.0f];
[[[self testView] layer] setBorderWidth:1.0f];
}
El testView
es un UIView que agregué en Interface Builder y configuré una salida. Esto es para asegurarse de que funciona de la misma manera en las dos capas que agrega explícitamente, así como en las capas dentro de las subvistas.
He probado esto en los simuladores para iOS5 a iOS6.1. Se da este resultado para mí en cada uno de ellos:

¿Hay alguna razón para no establecer shouldRasterize a SÍ? – memmons
Depende de la frecuencia con la que esté actualizando la capa. Si tiene la intención de configurarlo una vez y no actualizarlo nuevamente, rastrillarlo ayudará al rendimiento si está animando la capa. Sin embargo, si el contenido de la capa se actualiza con frecuencia, generará ese contenido como una imagen cada vez que cambie el contenido, lo que en realidad podría dañar su rendimiento de desplazamiento (suponiendo que esté desplazándose/animando). –
Necesita espacio entre UIBezierPath y bezierPathWithRoundedRect. –