IB_DESIGNABLE, IBInspectable - Le générateur d'interface ne se met pas à jour

91

J'ai l'ensemble de 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 référence Swift, ce problème se produisait également avec le code 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 défini sa sous-classe sur CustomView.

entrez la description de l'image ici

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

Lorsque je passe à l'inspection des attributs, je suis en mesure de définir ces IBInspectablepropriétés:

entrez la description de l'image ici

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

entrez la description de l'image ici

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

De plus, lorsque je règle le IBInspectable propriétés, j'obtiens un avertissement pour chacun:

IBDesignables - Ignorer l'attribut d'exécution défini par l'utilisateur pour le chemin de 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:

entrez la description de l'image ici


Je connais les problèmes de conformité 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 un "CustomView" (pas un "UIView" normal, qui n'a pas ces propriétés). Et si la vue n'était pas une "vue personnalisée", ces propriétés personnalisables n'apparaîtraient pas dans l'inspecteur d'attributs, n'est-ce pas? Mais quand Interface Builder essaie 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? S'il vous plaît laissez-moi savoir si j'ai omis certains détails importants, mais pour ce que cela vaut, j'ai suivi ce tutoriel exactement (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 a fonctionné comme un charme (j'avais l'intention de faire ce post la nuit dernière 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 .mfichier n'est peut-être pas inclus et que cela pourrait être à l'origine du problème. Je pensais sûrement que j'aurais fait tout mon possible pour que ce scénario soit le cas, mais j'ai quand même vérifié.

entrez la description de l'image ici

Quand j'ai commencé à essayer de faire cela, j'étais sous la compréhension que les IB_DESIGNABLEclasses devaient faire partie d'un UIKitcadre différent . Donc , à partir de cette première capture d' écran, vous pouvez voir que je mis en place un cadre « 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 cependant.

Ici, nous avons une capture d'écran indiquant qu'il CustomView.mest inclus pour être construit avec le CustomViewsframework:

entrez la description de l'image ici

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

  • CustomViews.framework est correctement inclus dans le projet principal.
  • OtherView.mest également inclus comme source de compilation, donc même si quelque chose ne va pas avec CustomView,OtherView devrait fonctionner, mais il génère des erreurs identiques.
  • Main.storyboardet LaunchScreen.xibapparaissent en rouge. Je n'ai aucune idée pourquoi, et je n'ai pas la moindre idée de pourquoi LaunchScreen.xib(je n'ai pas touché à ce fichier), bien que je puisse dire après avoir regardé d'autres projets, Main.storyboardapparaît également en rouge pour ces projets, et je suis ne rien faire avec IB_DESIGNABLEou IBInspectablelà.

entrez la description de l'image ici


J'ai essayé et réessayé 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 fin 2012). Les deux ordinateurs exécutent 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é qu'il pourrait s'agir d'une mauvaise RAM. Cela me semble exagéré. J'ai redémarré le projet plusieurs fois, redémarré l'ordinateur plusieurs fois. Il me semble que s'il y avait une mauvaise RAM sur un ordinateur d'environ 6 mois, que je verrais d'autres problèmes, et que ce problème serait moins cohérent. Mais ce problème exact persiste malgré le redémarrage à plusieurs reprises de l'ensemble du projet à partir de zéro et des redémarrages complets sur l'ordinateur.


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

nhgrif
la source
Eh bien, c'était juste une idée. J'ai supprimé CustomView.m de la cible, puis j'ai reçu des avertissements similaires lors de l'exécution de l'application.
Martin R
Cela semble être un vrai gremlin étant donné votre comparaison avec une machine apparemment identique (qui diffère en quelque sorte). Avez-vous essayé de publier sur des forums de développement? Il semble que vous voliez à l'aveugle sans informations supplémentaires, et votre processus semble raisonné et rationnel. L'avertissement "build" ne veut pas dire trop car Xcode regorge de messages d'erreur trompeurs. Pour les coups de pied, vous avez essayé Editor -> "debug selected view", non? (Cela ne fonctionnera probablement pas, mais cela vaut la peine d'être vérifié). De plus, est-ce que quelque chose apparaît dans l'application (de journalisation) de la console?
Chris Conover
J'ai le même problème. Mines avec un seul fichier xib contenant un IB_DESIGNABLE. Cependant, en vérifiant ma configuration, j'ai déjà l'actualisation automatique et j'ai maintenant essayé des rafraîchissements manuels, en effaçant d'abord les données dérivées, etc. Jusqu'à présent, rien n'a fonctionné. Ce qui est étrange, c'est que ce contrôle fonctionnait bien, puis il s'est arrêté. Et je ne pense pas avoir changé de code entre les deux. Fou.
drekka
Montrait des avertissements comme ci-dessus. Ont maintenant créé une deuxième classe avec le code copié à partir du designable IB original. Cette classe fonctionne parfaitement et lorsque je suis revenu à la classe non ouvrière d'origine, cela fonctionne maintenant très bien. De cela, j'ai conclu qu'il y a un cache quelque part (pas dans les données dérivées) qui n'est pas effacé jusqu'à ce que le designable ib d'origine soit échangé contre un autre designable ib. Le passage à un UIView ne semble pas effacer ce cache. Seul un autre ib designable. Allez comprendre :-)
drekka

Réponses:

75

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

  • Actualiser automatiquement les vues
  • Actualiser toutes les vues

J'ai cliqué sur "Actualiser toutes les vues" et après que Xcode ait réfléchi un peu, le storyboard a soudainement affiché ma vue comme prévu (appliquant correctement mes IBInspectablepropriétés).

entrez la description de l'image ici

J'ai ensuite repassé tout le processus pour confirmer que c'est la solution.

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

entrez la description de l'image ici

En cliquant sur "Afficher" pour moi les avertissements:

entrez la description de l'image ici

Un nouveau cette fois:

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, maintenant, les trois autres avertissements ont doublé en 6 étrangement.

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

Pourtant, jusqu'à ce point, tout ce que j'ai fait était des choses avec lesquelles je n'ai jamais joué à la maison. À la maison, ça a marché. J'ai donc activé "Actualiser automatiquement les vues" et créé un "FourthView" à tester - encore une fois, identique aux trois premiers.

Après avoir changé la classe de la vue en "FourthView", le libellé des désignables a dit "Mise à jour" pendant un court moment puis a finalement dit "À jour":

entrez la description de l'image ici

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


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

entrez la description de l'image ici

nhgrif
la source
2
Je cherchais en fait comment le désactiver, car il continue à être rendu en arrière-plan, ce qui ralentit vraiment les anciens MacBook. Merci!
Departamento B
Cela peut résoudre temporairement, mais consultez la réponse de @ Martin-Gilles Lavoie
Ashley Mills
22

J'ai quelques détails supplémentaires qui peuvent 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, dirigez-vous vers le navigateur de rapports dans votre espace de travail / projet XCode.

Dans le menu Editeur de XCode, appuyez sur (comme mentionné par nhgrif), l'option "Actualiser toutes les vues". Cela amènera IB à lancer une compilation pour tout un tas de choses auxquelles vous ne vous attendriez pas, j'en suis certain.

Dans le navigateur de rapports, cliquez sur «Par groupe» pour filtrer le contenu et consultez la section «Générateur d'interface». Vous verrez que dans le but de charger le framework de vues IBDesignable personnalisé, il compilera BEAUCOUP de choses. Le cas échéant de ces cibles ne se compile PAS, comme des cibles de test unitaire (peut-être obsolètes) (même si elles ne sont absolument pas liées au code qui charge ces vues ou storyboard), alors IB échouera au 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écents changements de refactorisation sur lesquels nous travaillons.

La plupart des modifications / corrections de code que j'ai effectuées pour qu'IB puisse charger et afficher correctement mes vues douanières lorsqu'elles ne sont pas liées ou même liées à ces classes, ni ne chargera jamais le storyboard au cours de l'exécution de ces tests unitaires. Pourtant, IB dépendait de la compilation de tout l'espace de travail pour que cela fonctionne.

Martin-Gilles Lavoie
la source
Hé, comment puis-je empêcher IB d'essayer de charger et d'afficher des vues non liées ou liées à ces classes?
HannahCarney
Je suppose que cela a à voir avec les dépendances d'en-tête. Que les classes désignables touchent d'autres classes, au moment où l'en-tête est vu, il construira ces implémentations associées. Apple joue avec le code du graphe de dépendance source dans XC7GM qui échoue complètement sur notre projet avec XCode plantant lors de la construction du graphe. Les 7.1betas suivants ne présentent pas le problème. Notre système de construction automatisé dépend toujours de la version 6.4 pour le moment, nous n'avons donc pas étudié comment résoudre ce problème davantage sous XC6.4. Nous allons passer directement à 7.1GM.
Martin-Gilles Lavoie
Si vous avez plusieurs cibles / projets, c'est absolument la bonne réponse et résout vraiment le problème - TOUTES les cibles doivent être construites proprement, je ne savais même pas qu'il y avait une section "Interface Builder" dans le navigateur de rapport! Toutes les autres réponses que j'ai vues sont essentiellement des gestes de main qui pourraient le réparer temporairement, mais c'est la solution définitive. Bien joué.
Ashley Mills le
3
Donc, d'après cela, nous pouvons conclure que l'attribut IB_DESIGNABLE est une merde totale et une perte de temps. Évitez simplement de l'utiliser.
m8labs
IB_DESIGNABLE n'a rien à voir avec le problème et la solution répertoriés ci-dessus. C'est simplement un indicateur NO-OP pour IB pour repérer les choses utilisables. Vous avez juste besoin de maintenir une maison propre.
Martin-Gilles Lavoie
22

Juste un petit conseil pour toute autre personne ayant ce problème: n'oubliez pas 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
GoldenJoe
la source
6

J'ai eu le même avertissement Ignoring user defined runtime attribute for key path .. même si je suis absolument sûr de n'avoir rien fait de mal avec ma classe de vue IBDesignable personnalisée.

Il s'est avéré que, dans mon cas, cela avait à voir avec le cache Xcode.

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

Purgez DerivedDataet l'avertissement est parti.

samwize
la source
1
Raccourci dans XCode pour obtenir le même résultat: ⌘⇧K
Mojo66
@ Mojo66 Je pense que Clean Build est différent de la purge du dossier DerivedData. Bien sûr, une version propre est parfois suffisante pour résoudre certains problèmes de mise en cache Xcode.
samwize
@ Mojo66 vous vouliez probablement dire ⌘⌥⇧K (cmd + alt + shift + K)
tzaloga
5

Si quelqu'un d'autre se heurte à 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 storyboard appelé customModule.

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

Ainsi, le XML de certaines vues s'est terminé par customClass = "ForwardArrow" customModule = "MainTargetNameWasHere"

Lorsque je les ai supprimés de la cible principale dans la construction, le storyboard n'a pas mis à jour MainTargetNameWasHere vers CustomViews qui est le cadre dans lequel il se trouvait et a commencé à indiquer qu'aucune classe n'a trouvé d'erreur.

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

Exemple de ma source:

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MUG-jc-2Ml" customClass="ForwardArrow" customModule="CustomViews">
Dave Thomas
la source
1
Putain de merde, ça me rend fou depuis un jour. Quel méchant petit bug.
GoldenJoe
5

À titre d'exemple, j'utilisais CheckboxButton via le pod et les graphiques de la case à cocher n'apparaissent jamais dans le storyboard alors que j'ai les mêmes problèmes décrits dans la question ici:

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

et

avertissement: IB Designables: Ignorer l'attribut d'exécution défini par l'utilisateur pour le chemin de clé "checkColor" sur l'instance de "UIView". Frappez une exception lors de la tentative de définition de sa valeur: [setValue: forUndefinedKey:]: cette classe n'est pas compatible avec le codage des valeurs de clé pour la clé checkColor.

La façon dont mon problème a été résolu é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.

Même Cheng
la source
4

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 dans l'IB, puis ajoutez une nouvelle classe personnalisée, les éléments personnalisables dans l'inspecteur d'identité ne sont pas supprimés et cela m'a causé cette erreur. Supprimez simplement tout et reconstruisez.entrez la description de l'image ici

HannahCarney
la source
J'ai fait exactement ce que vous avez dit et cela a résolu mon problème. Toutes les solutions précédentes exposées ici n'ont pas réussi. Merci beaucoup. ; o)
XLE_22
@ XLE_22 parfois ce sont les réponses que personne ne regarde qui le résout, hein? :)
HannahCarney
J'ai eu un problème où j'ai renommé une propriété IBInspectable sur quelques-uns de mes xib. Après cela, j'ai eu une tonne d'avertissements m'informant que XCode ne pouvait pas trouver la propriété maintenant renommée. La suppression de la propriété de l'inspecteur d'identité a résolu mon problème.
WBuck
1

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

J'avais des 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 résolu le problème (de code) avec le composant, j'ai tout actualisé une tonne de fois, mais toujours pas d'attributs dans l'inspecteur d'identité.

Finalement, j'ai remarqué qu'ils étaient de retour, mais uniquement dans l'inspecteur d'attributs (alt-apple-4) . Dès que je leur ai ajouté des valeurs là-bas, ils ont réapparu dans l'inspecteur d'identité

Gordon Dove
la source
1

La réponse de Dave Thomas ci-dessus m'a donné la solution (inverse) alors que ce n'est 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ù éditer le XML ... t besoin de!

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

Je viens de passer par la sonnerie sur ce problème. J'ai essayé toutes les choses énumérées ici et ailleurs sans aucune chance. C'est un storyboard qui fonctionnait bien pour toujours et il a soudainement cessé de fonctionner avec le problème "Ignorer l'attribut d'exécution défini par l'utilisateur ...".

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

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

la suppression de cela a fait disparaître tous les avertissements, même dans d'autres objets IBDesignable. Je n'ai aucune idée de la raison pour laquelle cette étape a résolu le problème, mais peut-être que cela aidera quelqu'un d'autre aussi.

IMFletcher
la source
3
vous manquez l'appel pour souper ici
RolandasR
0

J'avais le même problème et j'ai dû changer le cornerRadius et BorderWidth en String, puis le convertir en CGFloat, c'était la seule solution pour moi de pouvoir changer les valeurs et voir les changements dans le 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
    }
}
Chuy47
la source
Je pense qu'IBInspectable ne peut faire que certains types, alors peut-être que vous auriez dû utiliser à la Floatplace CGFloatet lancer cela à la place
Fonix