ios - UIButton con IB_DESIGNABLE emite una advertencia de atributo de tiempo de ejecución y no se procesa en Interface Builder
objective-c interface-builder (7)
Estoy ejecutando Xcode 6.1 y he estado usando IB_DESIGNABLE con IBInspectable para bastantes proyectos, pero de repente ya no funciona. He creado botones subclasificados que organizan la imagen y el título centrados verticalmente uno encima del otro y permiten al usuario establecer un ancho y color de borde a través de IB con IBInspectable.
Se registra la siguiente advertencia y no hay una vista previa disponible de mi código en drawRect:
warning: IB Designables: Ignoring user defined runtime attribute for key path "spacingBetweenLabelAndImage" on instance of "UIButton". Hit an exception when attempting to set its value: [<UIButton 0x7f9278591260> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key spacingBetweenLabelAndImage.
Sin embargo, el tiempo de ejecución se muestra como lo intenté y también respeta el mismo espacio personalizado que he agregado a través de IB.
Aquí está el código del menú que reorganiza el botón y el título:
#import "HamburgerButton.h"
IB_DESIGNABLE
@interface HamburgerImageButton : HamburgerButton
@property IBInspectable CGFloat spacingBetweenLabelAndImage;
@end
Implementación:
#import "HamburgerImageButton.h"
@implementation HamburgerImageButton
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGSize imageSize = self.imageView.frame.size;
CGSize titleSize = self.titleLabel.frame.size;
// Move the label left and the image right by half the width
CGFloat leftInset = titleSize.width / 2;
CGFloat rightInset = imageSize.width / 2;
CGFloat halfSpacing = self.spacingBetweenLabelAndImage == 0 ? 0 : self.spacingBetweenLabelAndImage / 2;
CGFloat topInset = imageSize.height / 2 + halfSpacing;
CGFloat bottomInset = titleSize.height / 2 + halfSpacing;
UIEdgeInsets imageInsets = UIEdgeInsetsMake(-bottomInset, leftInset, bottomInset, -leftInset);
UIEdgeInsets titleInsets = UIEdgeInsetsMake(topInset, -rightInset, -topInset, rightInset);
self.imageEdgeInsets = imageInsets;
self.titleEdgeInsets = titleInsets;
}
@end
Probablemente has notado que hereda HamburgerButton. Este botón de hamburguesa básico no tiene una imagen y solo dibuja el borde alrededor del botón. Este botón de hamburguesa básico tiene exactamente el mismo problema: no dibuja su borde en drawRect en IB y tiene el mismo tipo de errores. Aquí está ese código por el bien de la integridad:
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface HamburgerButton : UIButton
@property IBInspectable CGFloat borderWidth;
@property IBInspectable UIColor *borderColor;
@end
Implementación:
#import "HamburgerButton.h"
#import <QuartzCore/QuartzCore.h>
@implementation HamburgerButton
- (void)copyInspectables {
self.layer.borderWidth = self.borderWidth;
self.layer.borderColor = self.borderColor.CGColor;
}
- (void)drawRect:(CGRect)rect {
[self copyInspectables];
}
@end
Realmente no entiendo por qué solo lanza una advertencia y nada más. Realmente no cambié lo que hice. He comprobado el guión gráfico, es iOS 7 y superior, destinado a ejecutarse en Xcode 6 (más reciente).
Se queja de no poder encontrar ese valor en UIButton y eso es un poco raro porque lo he subclasificado.
Actualización: Así que cambié todo alrededor y funcionó. Ahora vuelve a cagarse, sin cambiar nada más. Creo que hay un error en Xcode 6.1 ...: /
He estado trabajando extensamente con Live Views desde sus introducciones y como muchas de las nuevas características de Xcode inicialmente, tiene algunas fallas. Todavía me gusta mucho y espero que se mejore en las versiones más nuevas.
Porque:
Live Views funciona con las propiedades de @property que obtienen una etiqueta especial IB_Designable que le dará a la clase de UI atributos adicionales a los que se puede acercar a través de los atributos de tiempo de ejecución definidos por el usuario que se establecerán a través del inspector de atributos. Verá que todas esas propiedades también existen en el inspector de identidad. La causa raíz del problema es que ya no puede asignar esos Atributos de tiempo de ejecución definidos por el usuario a las propiedades expuestas.
Tan pronto como abra un Guión gráfico o xib que use IB_Designable, Xcode volverá a compilar la pantalla en cada cambio si tiene activada la opción "Actualizar automáticamente vistas". Dado que su código influye en su interfaz de usuario, esto no tiene por qué ser un cambio en Interface Builder per se.
Con proyectos más simples en máquinas más rápidas, esto funciona bastante bien la mayoría de las veces. Con proyectos más grandes que también tienen más IB_Designable, la CPU simplemente no tiene la capacidad suficiente para mantenerse al día con usted y obtendrá una especie de error de tiempo de espera al procesar la interfaz de usuario. Esta es la causa de la "advertencia: IB Designables: ignorando el atributo de tiempo de ejecución definido por el usuario para la ruta clave" spacingBetweenLabelAndImage "en la instancia de" UIButton ". Presiona una excepción al intentar establecer su valor: [setValue: forUndefinedKey:]: esta clase es no es compatible con la codificación de valores de clave para el espaciado de la clave entre la etiqueta y la imagen ". error.
Tampoco actualizará su interfaz de usuario con su código personalizado. Sin embargo, esto no es un problema cuando lo ejecuta, porque en el tiempo de ejecución reflejará esos cambios.
Otra causa puede ser que su código simplemente no se compile cuando intenta compilar en segundo plano. Esto es inevitable cuando se está trabajando en el código, por lo que también se activa con frecuencia.
Solución:
Debemos asegurarnos de que su clase de vista personalizada se compile de nuevo para que las propiedades se puedan establecer correctamente a través de Interface Builder
- Mientras esté en un guión gráfico, vaya a "Editor" en el menú de la barra superior
- deselecciona "Actualizar automáticamente las vistas" si aún estaba encendido
- Cierra todas las pestañas de tu guión gráfico.
- Reconstruir el proyecto
- Corrige todos los errores de compilación si los hay
- Vuelva a abrir su guión gráfico.
- Vaya a "Editor" otra vez y haga clic en "Actualizar todas las vistas"
Las advertencias deberían haber desaparecido y, si funcionaban antes, también verá su código de vista personalizado.
Después de un comentario a continuación por sunkas: siempre es una muy buena idea clean su solución a fondo en caso de que surja algún problema extraño.
Intente cambiar su declaración " CGFloat
" para spacingBetweenLabelAndImage
en " NSNumber
".
Que yo sepa, no se puede llamar " setValue:
" en una variable de tipo C.
Cambiar la declaración de " spacingBetwenLabelAndImage
" a NSNumber también requerirá que cambie un poco de código también:
CGFloat halfSpacing = self.spacingBetweenLabelAndImage == 0 ? 0 : self.spacingBetweenLabelAndImage / 2;
podría convertirse en algo como:
CGFloat halfSpacing = (self.spacingBetweenLabelAndImage ? ([self.spacingBetweenLabelAndImage floatValue] / 2) : 0.0);
(No estoy 100% seguro de si esta es una traducción perfecta de la primera línea, pero quería mostrar cómo obtener un valor flotante de un NSNumber)
Si está seguro de que configura correctamente todos los configuradores, y si importó otros SDK en su proyecto y está teniendo este problema, marque ''Marcos y bibliotecas vinculadas'' en Destino - General.
Después de vincular correctamente algunos marcos de SDK, el error desapareció.
Tuve un problema similar, pero en realidad eliminé la propiedad de la clase y Interface Builder aún se quejaba de la propiedad perdida, difícil.
Probé muchas cosas, como limpiar, reconstruir ... ¡Pero nada funcionó!
Lo que realmente resolvió fue hacer clic derecho en el archivo del Guión Gráfico, seleccionando "Abrir como" y luego "Código fuente". Esto abrió el contenido XML del guión gráfico en el editor y pude buscar referencias a la propiedad que faltaba hasta que encontré la sección:
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute... keyPath="My Missing Property Name">
...
</userDefinedRuntimeAttributes>
Después de eliminar toda la sección, guardé el archivo y actualicé la vista en Interface Builder. ¡Ahora todas las advertencias se han ido!
Utilicé el método proporcionado por el Departamento B pero no funcionó. Sin embargo, solucioné mi problema por 1. Seleccionando las vistas de buggy del story board 2. Haciendo clic en (Editor - Depurar la vista seleccionada) Espero que esto ayude