web-dev-qa-db-fra.com

IB_DESIGNABLE, IBInspectable - Le constructeur d'interface ne met pas à jour

J'ai le code suivant:

CustomView.h

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface CustomView : UIView

@property (nonatomic) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable CGFloat borderWidth;
@property (nonatomic) IBInspectable CGFloat cornerRadius;

@end

CustomView.m

#import "CustomView.h"

@implementation CustomView

- (void)setBorderColor:(UIColor *)borderColor {
    _borderColor = borderColor;
    self.layer.borderColor = borderColor.CGColor;
}

- (void)setBorderWidth:(CGFloat)borderWidth {
    _borderWidth = borderWidth;
    self.layer.borderWidth = borderWidth;
}

- (void)setCornerRadius:(CGFloat)cornerRadius {
    _cornerRadius = cornerRadius;
    self.layer.cornerRadius = cornerRadius;
}

@end

(Pour Swift, ce problème se produisait également avec Swift))

CustomView.Swift

@IBDesignable
class CustomView : UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    @IBInspectable var borderColor : UIColor = UIColor.clearColor() {
        didSet {
            self.layer.borderColor = borderColor.CGColor
        }
    }

    @IBInspectable var borderWidth : CGFloat = 0.0 {
        didSet {
            self.layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var cornerRadius : CGFloat = 0.0 {
        didSet {
            self.layer.cornerRadius = cornerRadius
        }
    }
}

J'ai ajouté un UIView à un contrôleur de vue sur le storyboard et ai défini sa sous-classe sur CustomView.

enter image description here

Cela ajoute la ligne "Designables". Il est bloqué sur "Mise à jour" et l'info-bulle indique "En attente de la cible à construire". Il ne change jamais de ce statut.

Lorsque je passe à l'inspection d'attributs, je peux définir ces propriétés IBInspectable:

enter image description here

Et une fois définis, ils apparaissent également dans les "Attributs d’exécution définis par l'utilisateur":

enter image description here

Cependant, le statut "Designables" ne dépasse jamais le statut "Mise à jour" avec toujours la même info-bulle (j'ai essayé plusieurs fois de construire Cmd + B, rien ne change).

De plus, lors de la définition des propriétés IBInspectable, un message d'avertissement s'affiche pour chacune d'elles:

IBDesignables - Ignorance de l'attribut d'exécution défini par l'utilisateur pour le chemin d'accès à la clé "borderColor" sur l'instance de "UIView" ... cette classe n'est pas compatible avec le codage clé-valeur pour la clé borderColor.

Capture d'écran des avertissements générés:

enter image description here


Je connais bien les problèmes liés au codage clé-valeur et je sais généralement comment les résoudre ... mais je ne comprends pas comment résoudre ce problème ici. Selon l'inspecteur d'identité de la vue, la vue est une "CustomView" (et non une "UIView" standard qui ne possède pas ces propriétés). Et si la vue n'était pas un "CustomView", ces propriétés désignables ne seraient pas affichées dans l'inspecteur d'attributs, n'est-ce pas? Mais lorsque Interface Builder tente d'appliquer ces attributs à la vue, il revient à penser que la classe de la vue est "UIView" et ne peut pas appliquer les attributs.

De l'aide? Faites-moi savoir si j'ai omis certains détails importants, mais pour ce que cela vaut, J'ai suivi ce tutoriel à la lettre (autre que ObjC vs Swift). Il est également intéressant de noter que j'ai suivi ce tutoriel exactement sur une autre machine et que cela fonctionnait à merveille (j'avais l'intention de faire ce post hier soir, mais l'ordinateur sur lequel j'étais alors n'avait pas ce problème).


Sur la base des commentaires, il a été suggéré que le .m Le fichier n'est pas inclus et cela pourrait être à l'origine du problème. Je pensais sûrement que j'aurais fait tout ce qui était en mon pouvoir pour que ce scénario soit le cas, mais j'ai quand même vérifié.

enter image description here

Lorsque j'ai commencé à essayer de le faire, j'étais conscient que le IB_DESIGNABLE Les classes devaient faire partie d'un autre framework UIKit. Ainsi, à partir de cette première capture d'écran, vous pouvez voir que j'ai configuré un framework "CustomViews", qui a une classe, CustomView. Vous verrez également ici que j'ai également créé un OtherView, qui est identique à CustomView, sauf que ce n'est pas dans un cadre séparé. Le problème identique persiste sur le storyboard entre les deux classes.

Ici, nous avons une capture d'écran indiquant que CustomView.m est inclus pour être construit avec le framework CustomViews:

enter image description here

Pendant ce temps, la capture d'écran suivante indique plusieurs choses:

  • CustomViews.framework est correctement inclus dans le projet principal.
  • OtherView.m est également inclus en tant que source de compilation, donc même si quelque chose ne va pas avec CustomView, OtherView devrait fonctionner, même s'il génère des erreurs identiques.
  • Main.storyboard et LaunchScreen.xib apparaissent en rouge. Je ne sais pas pourquoi et je n'ai aucune idée du pourquoi LaunchScreen.xib devrait (je n’ai pas touché ce fichier), bien que je puisse dire après avoir examiné d’autres projets, Main.storyboard apparaît également en rouge pour ces projets, et je ne fais rien avec IB_DESIGNABLE ou IBInspectable ici.

enter image description here


J'ai essayé et réessayé cela plusieurs fois maintenant. Cela fonctionne à chaque fois sur mon ordinateur à la maison - je ne peux pas reproduire le problème décrit dans cette question à la maison. Au travail, ça ne marche jamais. Le problème décrit dans cette question se produit à chaque fois.

Les deux ordinateurs sont des Mac Minis achetés neufs cette année (pas les nouveaux modèles, modèle de fin 2012). Les deux ordinateurs fonctionnent sous OS X Yosemite 10.10. Les deux ordinateurs exécutent Xcode version 6.1. À la maison, la construction est (6A1052d). Ce matin, je peux confirmer que les deux ordinateurs exécutent des versions identiques de Xcode.

D'autres m'ont suggéré que cela pourrait être une mauvaise RAM. Cela me semble aller trop loin. J'ai redémarré le projet plusieurs fois, l'ordinateur plusieurs fois. Il me semble qu’il y avait un mauvais RAM sur un ordinateur âgé de 6 mois environ, que je verrais d’autres problèmes et que ce problème serait moins constant. Ce problème persiste malgré de nombreux fois de redémarrer l’ensemble du projet et de le redémarrer complètement sur l’ordinateur.


Il convient de noter que si je compile et exécute réellement ce projet, la vue personnalisée avec les propriétés IBInspectable s'affiche en réalité comme je l'espère, le storyboard l'affichera. J'imagine que ce serait le cas même sans le IB_DESIGNABLE et IBInspectable directives, car elles sont créées en tant qu’attributs d’exécution définis par l’utilisateur.

88
nhgrif

Sur la base de la suggestion de chrisco de déboguer la vue sélectionnée (ce que j'avais déjà fait, mais je suis allé essayer à nouveau pour faire bonne mesure), j'ai remarqué quelques autres options au bas du menu Editeur.

  • Actualiser automatiquement les vues
  • Actualiser toutes les vues

J'ai cliqué sur "Actualiser toutes les vues" et, après réflexion, Xcode a soudainement affiché mon affichage comme prévu (en appliquant correctement mes propriétés IBInspectable).

enter image description here

J'ai ensuite répété tout le processus pour confirmer que c'était la solution.

J'ai créé une nouvelle classe, ThirdView. Cette classe est identique aux autres, encore. J'ai changé la classe de ma vue en ThirdView et j'ai quelque chose de légèrement différent cette fois-ci:

enter image description here

En cliquant sur "Show" pour moi aux avertissements:

enter image description here

Un nouveau cette fois-ci:

Utilisation de la classe UIView pour un objet avec une classe personnalisée car la classe ThirdView n'existe pas.

Ce n'est pas vraiment plus utile que ce qui existait déjà. De plus, les trois autres avertissements ont été doublés étrangement.

Quoi qu'il en soit, si je clique à nouveau sur "Actualiser toutes les vues" dans le menu déroulant Editeur, toutes les erreurs disparaissent et, une fois encore, la vue s'affiche correctement.

Pourtant, jusqu'à présent, tout ce que je faisais était une chose que je n'avais jamais foirée à la maison. À la maison, ça marchait. J'ai donc activé l'option "Actualiser automatiquement les vues" et créé un "FourthView" à tester, identique une fois encore aux trois premiers.

Après avoir changé la classe de la vue en "FourthView", le label "Designables" a déclaré "Mise à jour" pendant un court moment, puis a finalement déclaré "Mise à jour":

enter image description here

Alors, j'ai vérifié mon ordinateur à la maison. "Actualiser automatiquement les vues" est activé sur l'ordinateur qui fonctionnait toujours. Il a été éteint à l'ordinateur qui ne l'était pas. Je ne me souviens jamais d'avoir touché cette option de menu. Je ne peux même pas vous dire avec certitude si cela existait avant Xcode 6. Mais c'est cette option qui faisait la différence.


TL; DR, si vous rencontrez le même problème que celui décrit dans la question, assurez-vous que l'option "Actualiser automatiquement les vues" est activée (ou manuellement "Actualiser toutes les vues" lorsque vous avez besoin d'une mise à jour dans IB):

enter image description here

73
nhgrif

Juste un conseil rapide pour quiconque ayant ce problème: rappelez-vous de spécifier le type de la variable.

// Doesn't show up in IB
@IBInspectable var includeLeftSection = true

// Shows now that it knows the type
@IBInspectable var includeLeftSection : Bool = true
22
GoldenJoe

J'ai quelques détails supplémentaires susceptibles d'empêcher le chargement de vos classes IBDesignable.

Sélectionnez votre storyboard/xib problématique où vos vues personnalisées doivent s'afficher.

Dans la zone du navigateur, accédez au Navigateur de rapports dans votre espace de travail/projet XCode.

Dans le menu Editeur de XCode, cliquez sur "Refresh All Views" (comme mentionné par nhgrif). Cela obligera IB à lancer une compilation pour tout un tas de choses auxquelles vous, je suis certain, ne vous attendiez pas.

Dans le navigateur de rapports, cliquez sur "Par groupe" pour filtrer le contenu et consultez la section "Interface Builder". Vous verrez que, dans le but de charger le framework de vues personnalisé IBDesignable, il compilera BEAUCOUP de choses. Si toute de ces cibles ne compilent PAS, telles que des cibles de test unitaire (peut-être déconseillées) (même si elles n'ont aucun rapport avec le code qui charge ces vues ou ce storyboard), alors IB échouera lors du chargement de votre dll.

Dans mon cas, IB a essayé de compiler 8 cibles, dont 4 où des tests unitaires n’avaient pas été mis à jour depuis les récentes modifications de refactoring sur lesquelles nous travaillions.

La plupart des modifications/corrections de code que j'ai apportées pour que IB puisse charger et afficher correctement les vues de douane non liées ou même liées à ces classes, pas plus qu'il ne chargerait le storyboard lors de l'exécution de ces tests unitaires. Pourtant, IB dépendait de l’ensemble de l’espace de travail en cours de compilation pour pouvoir fonctionner.

20

J'ai eu le même avertissement Ignoring user defined runtime attribute for key path .. bien que je sois absolument sûr de ne rien avoir de mal avec ma classe d'affichage IBDesignable personnalisée.

En fait, dans mon cas, cela a à voir avec le cache Xcode.

rm -rf ~/Library/Developer/Xcode/DerivedData/*

Purger DerivedData et l'avertissement est parti.

6
samwize

Comme mon exemple, j'utilisais CheckboxButton via pod et les graphiques de la case à cocher n'apparaissent jamais dans le story-board, alors que j'ai les mêmes problèmes que ceux décrits dans la question:

warning: IB Designables: Utilisation de la classe UIView pour objet avec une classe personnalisée car la classe CheckboxButton n’existe pas

et

warning: IB Designables: Ignorant l’attribut d’exécution défini par l’utilisateur pour le chemin de clé "checkColor" sur l’instance de "UIView". Hit une exception en essayant de définir sa valeur: [setValue: forUndefinedKey:]: cette classe n'est pas compatible avec le codage de valeur de clé pour la clé checkColor.

La manière résolue mon problème était de fournir le module avec le nom CheckboxButton comme ci-dessous:

Remarque: vous devez remplacer CheckboxButton par le nom du module que vous utilisez.

5
Even Cheng

Au cas où un autre se heurterait à l'erreur, la classe IB Designables n'existe pas, pour la même raison que moi. La meilleure réponse n’était pas mon problème ... mais voici un problème légèrement lié ...

Il existe une propriété cachée dans le code source du story board, appelée customModule.

Par exemple, j'ai eu une classe appelée ForwardArrow dans un cadre séparé que j'ai accidentellement ajouté à ma cible principale.

Ainsi, le code XML de certaines vues a été personnalisé en tant que customClass = "ForwardArrow" customModule = "MainTargetNameWasHere"

Lorsque je les ai supprimés de la cible principale dans la construction, le scénario n'a pas mis à jour MainTargetNameWasHere to CustomViews, qui est le cadre dans lequel il a été localisé. Il a commencé à donner à cette classe une erreur introuvable.

Donc TLDR; Assurez-vous que si votre IBDesignable se trouve dans un autre framework, l'attribut xml customModule de votre story-board est défini sur la bonne valeur. Et si ce n'est pas du tout, ajoutez-le.

Exemple de ma source:

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MUG-jc-2Ml" customClass="ForwardArrow" customModule="CustomViews">
5
Dave Thomas

J'ai personnellement résolu ce problème en utilisant le bouton "-" pour supprimer le contenu de mon inspecteur d'identité. Lorsque vous supprimez des classes personnalisées, modifiez le contenu de l'IB, puis ajoutez une nouvelle classe personnalisée, les éléments désignables de l'inspecteur d'identité ne sont pas supprimés, ce qui m'a causé l'erreur. Supprimez tout et reconstruisez. enter image description here

4

Je sais que c'est répondu, mais voici une autre expérience.

J'avais quelques problèmes sans rapport avec ce problème, mais dans le processus, j'ai supprimé @IBInspectable des vars de ma classe et supprimé les attributs de l'inspecteur d'identité (alt-Apple-3).

Après avoir corrigé le problème (de code) avec le composant, j'ai tout rafraîchi une tonne de fois, mais toujours aucun attribut dans l'inspecteur d'identité.

Finalement, j'ai remarqué qu'ils étaient de retour, mais seulement dans l'inspecteur d'attributs (alt-Apple-4). Dès que j’y ai ajouté des valeurs, ils ont réapparu dans l’inspecteur d’identité

1
Gordon Dove

La réponse de Dave Thomas ci-dessus m'a donné la solution (inversée) alors que ce n'était pas le cas des autres (données dérivées, éditeur> Actualiser), mais par souci de clarté au cas où les gens ne savent pas où XML ... vous n'en avez pas besoin!

  1. Dans votre fichier de storyboard, sélectionnez la vue problématique
  2. Dans la barre latérale droite, sélectionnez l’onglet Inspecteur d’identité (3ème option à gauche).
  3. Vous aurez votre classe personnalisée, qui devrait déjà être définie, et le Module. Pour moi, c'était vide, et j'obtenais les mêmes erreurs que OP. J'ai défini le Module avec mon nom de projet et BAM - il a commencé à fonctionner après la reconstruction!
1
whycodewhyyyy

J'avais le même problème et je devais changer le cornerRadius et le BorderWidth en String, puis le convertir en CGFloat. C'était la seule solution pour moi de pouvoir modifier les valeurs et voir les modifications apportées au constructeur d'interface.

@IBInspectable var borderColor: UIColor? {
    didSet {
        layer.borderColor = borderColor!.CGColor
    }
}

@IBInspectable var borderWidth: String? {
    didSet {
        layer.borderWidth = CGFloat(Int(borderWidth!) ?? 0)
    }
}

@IBInspectable var cornerRadius: String? {
    didSet {
        layer.cornerRadius = CGFloat(Int(cornerRadius!) ?? 0)
        layer.masksToBounds = layer.cornerRadius > 0
    }
}
0
Chuy47

Je viens de traverser la sonnerie sur ce problème. J'ai essayé toutes les choses énumérées ici et ailleurs sans aucune chance. C'est un story-board qui a bien fonctionné pour toujours et qui a soudainement cessé de fonctionner avec le problème "Ignorer les attributs d'exécution définis par l'utilisateur ...".

Pour une raison quelconque, supprimer ce code de l'un de mes IBDesignable l'a corrigé:

-(void)viewDidLoad {
    self.clipsToBounds = YES;
}

cette suppression a fait disparaître tous les avertissements, même dans d'autres objets IBDesignable. Je ne sais pas du tout pourquoi cette étape a réglé le problème, mais peut-être que cela aidera aussi quelqu'un d'autre.

0
IMFletcher