UIView shadow e InterfaceBuilder

Quiero agregar una sombra con CALayer a una Vista de la UI (Imagen). El siguiente código funciona generalmente bien

previewImage.layer.shadowColor = [[UIColor blackColor] CGColor]; previewImage.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); previewImage.layer.shadowOpacity = 1.0f; previewImage.layer.shadowRadius = 8.0f; 

Sin embargo, esto solo funciona si creo esa vista mediante progtwigción y la agrego como una subvista a mi vista principal. Cuando esa vista está configurada en InterfaceBuilder y se define como un IBOutlet UIImageView, esto NO funciona. No aparece sombra. Entonces, ¿qué me falta aquí?

No estoy seguro de cuál es el problema: asegúrese de que la propiedad clipsToBounds esté configurada en NO . Puede hacer esto en viewDidLoad después de cargar desde el file nib haciendo reference a su IBOutlet. No debería necesitar envolverlo en otra vista.

Editar

A la luz de que necesita que su image sea escalada con el aspecto de relleno, puede usar la propiedad UIImageView de la capa subyacente de UIImageView para "simular" el efecto del recorte de contenido. contentsRect es un rectángulo en el espacio de coorderadas de la unidad del contenido de la capa (en este caso, su image) que define un sub-rectángulo de los contenidos que deben dibujarse.

Con un poco de matemáticas, podemos encontrar este rectángulo comparando el tamaño de la vista de la image con el tamaño de la image (teniendo en count el aspecto de la escala de relleno):

 CGSize imageViewSize = previewImage.size; CGSize imageSize = previewImage.image.size; // Find the scaling requinetworking for the image to fit the image view (as for aspect fill). CGFloat imageWidthScale = fabsf(imageViewSize.width / imageSize.width); CGFloat imageHeightScale = fabsf(imageViewSize.height / imageSize.height); CGFloat imageScale = (imageWidthScale > imageHeightScale) ? imageWidthScale : imageHeightScale; // Determine the new image size, after scaling. CGSize scaledImageSize = CGSizeApplyAffineTransform(imageSize, CGAffineTransformMakeScale(imageScale, imageScale)); // Set the layer's contentsRect property in order to 'clip' the image to the image view's bounds. previewImage.layer.contentsRect = CGRectMake(((scaledImageSize.width - imageViewSize.width) / 2.0f) / scaledImageSize.width, ((scaledImageSize.height - imageViewSize.height) / 2.0f) / scaledImageSize.height, imageViewSize.width / scaledImageSize.width, imageViewSize.height / scaledImageSize.height); 

Al hacer esto, puede dejar clipsToBounds configurados en NO para la vista de su image, pero la image seguirá apareciendo recortada. Si necesita cambiar el tamaño de la vista de la image, podría ser conveniente ajustar este código en un método que tome UIImageView como un parámetro.

Espero que esto ayude.

Agregue un file llamado UIView.swift en su proyecto (o simplemente pegue esto en cualquier file):

 import UIKit @IBDesignable extension UIView { /* The color of the shadow. Defaults to opaque black. Colors created * from patterns are currently NOT supported. Animatable. */ @IBInspectable var shadowColor: UIColor? { set { layer.shadowColor = newValue!.CGColor } get { if let color = layer.shadowColor { return UIColor(CGColor:color) } else { return nil } } } /* The opacity of the shadow. Defaults to 0. Specifying a value outside the * [0,1] range will give undefined results. Animatable. */ @IBInspectable var shadowOpacity: Float { set { layer.shadowOpacity = newValue } get { return layer.shadowOpacity } } /* The shadow offset. Defaults to (0, -3). Animatable. */ @IBInspectable var shadowOffset: CGPoint { set { layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y) } get { return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height) } } /* The blur radius used to create the shadow. Defaults to 3. Animatable. */ @IBInspectable var shadowRadius: CGFloat { set { layer.shadowRadius = newValue } get { return layer.shadowRadius } } } 

Entonces estará disponible en Interface Builder para cada vista en el Panel de Utilidades> Inspector de Atributos:

Panel de Utilidades

Ahora puedes configurar fácilmente la sombra.

Notas:
– La sombra solo aparecerá en time de ejecución.
clipsToBounds debe ser falso (por defecto es)

Sé que esta pregunta es larga, pero recientemente estuve en una situación similar, así que decidí poner mi respuesta para aquellos que se encuentran en una situación como esta.

Quería poder establecer borderColor y shadowColor en una UIView través del Interface Builder, pero el tipo de propiedad borderColor de una capa es CGColor (al igual que shadowColor ), que no es uno de los types que se pueden cambiar en el definido por el usuario atributo de time de ejecución.

Entonces hice una extensión para CALayer y agregué dos properties llamadas borderColorIB y shadowColorIB que son de tipo UIColor:

RuntimeAttributes.h

 @import QuartzCore; @interface CALayer (IBConfiguration) @property(nonatomic, assign) UIColor* borderColorIB; @property(nonatomic, assign) UIColor* shadowColorIB; @end 

RuntimeAttributes.m

 #import <UIKit/UIKit.h> #import "RuntimeAttributes.h" @implementation CALayer (IBConfiguration) -(void)setBorderColorIB:(UIColor*)color { self.borderColor = color.CGColor; } -(UIColor*)borderColorIB { return [UIColor colorWithCGColor:self.borderColor]; } -(void)setShadowColorIB:(UIColor*)color { self.shadowColor = color.CGColor; } -(UIColor*)shadowColorIB { return [UIColor colorWithCGColor:self.shadowColor]; } @end 

Ahora ya puedo configurar estas dos properties a través de Interface Builder así:

  1. En la sección 'attributes de time de ejecución definidos por el usuario' (Identity inspector)
  2. Asegúrese de que se selecciona UIView y agregue los siguientes attributes de time de ejecución:

    • layer.borderWidth, Number, 1
    • layer.borderColorIB, Color, someColor <- my custom property to set the borderColor
    • layer.shadowColorIB, Color, someColor <- my custom property to set the shadowColor
    • layer.shadowOpacity, Number, 0.8
    • layer.shadowOffset, tamaño, {5,5}
    • layer.cornerRadius, Number, 5

Aquí hay una image para mostrar cómo lo hice:

introduzca la descripción de la imagen aquí

… y El resultado será evidente durante el time de ejecución, no en Xcode:

introduzca la descripción de la imagen aquí

¡Espero que esto pueda ayudar a algunas personas!