UIButton avec IB designable lance un avertissement d'attribut d'exécution et ne rend pas dans Interface Builder

j'exécute Xcode 6.1 et J'ai utilisé IB_DESIGNABLE avec IBInspectable pour plusieurs projets déjà mais tout d'un coup il ne fonctionne plus. J'ai créé des boutons subclassés qui arrangent l'image et le titre verticalement centrés l'un sur l'autre et permettent à l'utilisateur de définir une largeur de bordure et la couleur à travers IB avec IBInspectable.

l'avertissement suivant est enregistré et il n'y a pas d'aperçu disponible de mon code dans 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.

encore, runtime il rend comme je l'ai prévu pour rendre et il honore également ce même espacement personnalisé que j'ai ajouté par IB.

voici le code du menubutton qui réarrange le bouton et le titre:

#import "HamburgerButton.h"

IB_DESIGNABLE
@interface HamburgerImageButton : HamburgerButton

@property IBInspectable CGFloat spacingBetweenLabelAndImage;

@end

mise en œuvre:

#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

vous avez probablement remarqué qu'il hérite HamburgerButton. Ce bouton hamburger de base n'a pas d'image et il ne dessine la frontière autour de la bouton. Ce bouton hamburger de base a exactement le même problème: il ne tire pas son bord dans drawRect en IB et il a le même type d'erreurs. Voici ce code par souci d'exhaustivité:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface HamburgerButton : UIButton

@property IBInspectable CGFloat borderWidth;
@property IBInspectable UIColor *borderColor;

@end

mise en œuvre:

#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

Je ne comprends pas vraiment pourquoi il lance un avertissement et rien d'autre. Je n'ai pas vraiment changé ce que j'ai fait. J'ai vérifié le storyboard, il est iOS 7 et plus, destiné à fonctionner en Xcode 6 (dernier).

il se plaint de ne pas pouvoir trouver cette valeur sur UIButton et c'est un peu bizarre parce que je l'AI sous-classé.


mise à Jour: Alors, j'ai changé tout ce qui l'entoure et cela a fonctionné. Maintenant, il se détend à nouveau, sans rien changer d'autre. Je pense qu'il y a un bug dans Xcode 6.1... : /

40
demandé sur Departamento B 2014-10-30 17:59:14

7 réponses

j'ai beaucoup travaillé avec des vues en direct depuis ses introductions et comme beaucoup de nouvelles fonctionnalités dans Xcode initialement, il a quelques défauts. Pourtant, je l'aime beaucoup et j'espère qu'il sera amélioré dans les versions plus récentes.

Cause:

les vues en direct fonctionnent avec les propriétés @property qui reçoivent une étiquette IB_Designable spéciale qui donnera les attributs supplémentaires de la classe UI qu'elle peut aborder via les attributs Runtime définis par L'utilisateur qui seront définis par L'Inspecteur des attributs. Vous verrez que toutes ces propriétés existent aussi dans L'Inspecteur D'identité. La cause fondamentale du problème est qu'il ne peut plus mapper les attributs D'exécution définis par L'utilisateur aux propriétés exposées.

dès que vous ouvrez un Storyboard ou xib qui utilise IB_Designable, Xcode recompilera l'écran à chaque changement si vous avez activé" rafraîchir automatiquement les vues". Puisque votre code influence votre UI aussi bien cela ne doit pas être un changement dans Interface Builder en soi.

Avec des projets simples sur des machines plus rapides, cela fonctionne assez bien la plupart du temps. Avec de plus grands projets qui ont aussi plus IB_Designable le CPU n'a tout simplement pas assez de capacité pour vous suivre et vous obtiendrez une sorte d'erreur de temporisation pendant le rendu de L'UI. C'est la cause de "warning: IB Designables: Ignoring user defined runtime attribut for key path "spacingBetweenLabelAndImage" on instance of "UIButton". Appuyez sur une exception lorsque vous essayez de définir sa valeur: [ setValue:forUndefinedKey:]: cette classe n'est pas conforme aux codes de valeurs clés pour la clé spacingBetweenLabelAndImage.""1519100920 d'erreur".

il ne mettra plus à jour votre UI avec votre code personnalisé. Ce n'est pas un problème quand vous l'exécutez, parce qu'au moment de l'exécution il reflétera ces changements.

une autre cause peut être que votre code ne se compile pas quand il essaie de compiler en arrière-plan. Cela est inévitable lorsque vous travaillez sur le code de sorte qu'il déclenche fréquemment ainsi.

Solution:

nous devons nous assurer que votre classe de vue personnalisée se compile à nouveau pour que les propriétés puissent être réglées avec succès via Interface Builder

  • pendant que dans un storyboard, aller à "Editeur" dans le menu de la barre du haut
  • désélectionner "rafraîchir automatiquement les vues" si elle était encore allumée
  • fermez tous vos onglets de storyboard
  • reconstruire le projet
  • corriger toutes les erreurs de construction s'il y en a
  • rouvrez votre storyboard.
  • allez à nouveau à "Editeur" et cliquez sur "rafraîchir toutes les vues"

les Avertissements devraient être partis et si cela a fonctionné avant vous verrez votre code de vue personnalisé à nouveau ainsi.

D'après un commentaire ci-dessous de sunkas: c'est toujours une très bonne idée de nettoyer votre solution soigneusement en cas de problèmes bizarres qui persistent.

65
répondu Departamento B 2017-05-23 11:54:56

comment j'ai personnellement fixé ceci:

dans l'inspecteur d'identité dans les attributs D'exécution définis par L'utilisateur, j'ai remarqué que J'avais un ancien élément IB_Inspectable que j'avais supprimé de mon code, mais qu'il y était toujours. Retrait avec le bouton - se débarrasser de cette erreur.

identityinspector

23
répondu Hannah Louisa Carney 2017-08-30 01:38:20

essayez de changer votre" CGFloat " déclaration pour spacingBetweenLabelAndImage en" NSNumber ".

autant que je sache, vous ne pouvez pas appeler setValue: " sur une variable de type C .

changer la déclaration de " spacingBetwenLabelAndImage "en NN number vous exigerait aussi de changer un peu de code aussi:

CGFloat halfSpacing = self.spacingBetweenLabelAndImage == 0 ? 0 : self.spacingBetweenLabelAndImage / 2;

pourrait devenir quelque chose comme:

CGFloat halfSpacing = (self.spacingBetweenLabelAndImage ? ([self.spacingBetweenLabelAndImage floatValue] / 2) : 0.0);

(Je ne suis pas sûr à 100% Si c'est une traduction parfaite de la première ligne, mais je voulais montrer comment obtenir un floatValue d'un NSNumber)

5
répondu Michael Dautermann 2017-05-23 12:17:59

j'ai utilisé la méthode Departamento B fournie mais elle n'a pas vraiment fonctionné. Cependant, j'ai résolu mon problème en 1. Sélection des vues de buggy du story board 2. En cliquant sur (Éditeur - Debug vue sélectionnée) Espérons que cette aide

1
répondu Martin Z 2015-09-18 18:53:08

j'ai eu un problème similaire, mais j'ai effectivement retiré la propriété de la classe et Interface constructeur se plaignait toujours de la propriété manquante, difficile.

a essayé beaucoup de choses, comme le nettoyage, la reconstruction... Mais rien n'a fonctionné!

ce qui a vraiment résolu, c'est un clic droit dans le fichier Storyboard, en sélectionnant" Ouvrir sous "et ensuite"code Source". Cela a ouvert le contenu XML de storyboard dans l'éditeur et j'ai pu chercher des références à la propriété manquante jusqu'à ce que je trouve la section:

<userDefinedRuntimeAttributes>
    <userDefinedRuntimeAttribute... keyPath="My Missing Property Name">
    ...
</userDefinedRuntimeAttributes>

après avoir supprimé toute la section, j'ai sauvegardé le fichier et rafraîchi la vue dans Interface Builder. Maintenant tous les avertissements ont disparu!

1
répondu rmartinsjr 2016-06-26 17:42:16

si vous êtes sûr que vous réglez tous les setters correctement, et si vous avez importé quelques autres SDK dans votre projet et vous obtenez ce problème, cochez' cadres et bibliothèques liés ' dans Target - General.

après avoir correctement relié certains cadres SDK, l'erreur a disparu.

0
répondu Maggie Phillips 2016-05-17 04:57:10

j'ai eu cette erreur, quand a deux cibles. L'un avec mon projet principal et l'autre avec target, où je tiens des classes configurables (pour une construction plus rapide).

Le problème était qu'il manquait un Module dans le storyboard.

enter image description here

0
répondu Nik Kov 2016-12-29 08:14:59