web-dev-qa-db-fra.com

Erreurs IBDesignable lors de l'ajout à la cible de tests

J'ai une simple sous-classe UIButton qui implémente IBDesignable avec une IBInspectable var:

@IBDesignable class Button: UIButton {
    @IBInspectable var borderColor: UIColor = UIColor.whiteColor() {
        didSet { layer.borderColor = borderColor.CGColor }
    }
}

Je n'utilise pas cela dans un cadre et cela fonctionne dans Interface Builder comme prévu. Cependant, une fois que j'ajoute cette sous-classe à ma cible Tests, elle arrête le rendu en direct et j'obtiens les erreurs suivantes:

Main.storyboard: error: IB Designables: Failed to update auto layout status: dlopen(TestTests.xctest, 1): Library not loaded: @rpath/XCTest.framework/XCTest
Referenced from: TestTests.xctest
Reason: image not found

Main.storyboard: error: IB Designables: Failed to render instance of Button: dlopen(TestTests.xctest, 1): Library not loaded: @rpath/XCTest.framework/XCTest
Referenced from: TestTests.xctest
Reason: image not found

Si je supprime IBDesignable et les IBInspectable vars, les erreurs disparaissent - malheureusement, le rendu en direct dans Interface Builder.

Comment tester contre une classe IBDesignable sans ces erreurs?

20
Adolfo

Au début, je pensais que c'était une sorte de bogue dans Xcode. Voici la solution de contournement que j'ai trouvée:

ÉTAPE 1

Marquez votre classe et vos propriétés comme étant public.

@IBDesignable public class Button: UIButton {
    @IBInspectable public var borderColor: UIColor = UIColor.whiteColor() {
        didSet { layer.borderColor = borderColor.CGColor }
    }

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

ÉTAPE 2

Importez votre module d'application à partir de votre module "Tests". 

Par exemple, en supposant que votre application s'appelle MyGreatApp, dans votre MyGreatAppTests/MyGreatAppTests.Swift:

import UIKit
import XCTest
import MyGreatApp

class MyGreatAppTests: XCTestCase {

    func testExample() {
        let btn = Button()
        btn.borderColor = UIColor.redColor()
        XCTAssertEqual(UIColor(CGColor:btn.layer.borderColor), UIColor.redColor(), "borderColor")
    }
}

Vous n'avez pas besoin d'ajouter 'Button.Swift' à votre cible "Tests".

ÉTAPE 3 (pour Swift)

Dans votre storyboard, sélectionnez explicitement le module MyGreatApp pour toute classe personnalisée au lieu de laisser Xcode utiliser le module actuel.

Interface Builder select main target module

17
rintaro

Votre question décrit exactement les circonstances que j'ai vécues. L'erreur est également visible dans l'inspecteur d'attributs sous vos propres attributs.

Voici la solution de contournement qui a fonctionné pour moi:

Étape 1 Supprimez tous les @IBDesignable et @IBInspectable de votre code source.

Étape 2 Retournez au constructeur d'interfaces. L'erreur est toujours là. 

Étape 3 Redémarrez XCode, reconstruisez votre projet. Les erreurs doivent être effacées.

Étape 4 Ajoutez tous les @IBDesignable et @IBInspectable à votre code source.

Après cette étape, j'ai pu poursuivre mon projet sans aucun problème.

Ma théorie explique pourquoi cela fonctionne, c'est que le constructeur d'interface met en cache des éléments qui ne sont pas supprimés (et reconstruits ultérieurement) lorsque vous effectuez un projet -> nettoyer.

L’autre réponse (importer votre module principal dans votre module de test) est une bonne idée et a permis de résoudre certains problèmes désagréables dans le passé, mais pas celui-ci.

15
Gerd Castan

La solution est très simple. Vous devez supprimer votre cible de test et la recréer depuis le début. Lorsque j'ai déplacé le projet vers Xcode 7, j'ai été averti que ma cible de test était endommagée. Alors j'ai décidé de le mettre en place une fois de plus. CELA A FONCTIONNÉ! .

De plus, vous n’attachez ni vos storyboards, ni même une classe à votre cible de test. S'il vous plaît ne le faites pas comme ça:

 enter image description here

Au lieu de cela, faites-le de cette façon:

 enter image description here

Donc, supprimez simplement tout fichier de votre cible de test (y compris les classes avec @IBDesignables), puis si vous avez besoin d'accéder à vos classes dans votre cible de test, utilisez simplement @testable import MyApp:

 enter image description here

Cela fonctionne et toutes les erreurs avec IBDesignables disparaîtront. Prendre plaisir:-)

3

Qu'est-ce qui cause ça?

Cette erreur apparaît lorsque deux événements se produisent:

  1. Vous incluez tout fichier contenant @IBDesignable ou @IBInspectable dans votre cible de test.
  2. Vous ouvrez votre fichier .storyboard ou .xib (contenant vos vues désignables/inspectables).

Comment puis-je empêcher cela?

Non plus:

  1. N'incluez pas de fichiers contenant @IBDesignable ou @IBInspectable dans votre cible de test. (Si vous testez simplement quelques fichiers de modèle isolés, ils peuvent rester membres de votre cible de test.)
  2. Supprimez tous les fichiers de votre application de votre cible de test (comme illustré dans Réponse de Bartłomiej ), et à la place importez le module de votre application dans votre fichier de test} _ (par exemple @testable import MyAppvoir ici pour plus de détails .) Il s'agit de la meilleure pratique, vous permettant de continuer à tester vos vues pouvant être désignées/inspectables ainsi que tout code de modèle de votre application.

Comment puis-je le résoudre une fois que c'est déjà arrivé?

Le problème avec cette erreur est qu’elle ne disparaît pas automatiquement une fois le problème résolu, car IB risque de mettre en cache quelque chose comme Gerd suggère dans sa réponse .

Ce que j’ai trouvé, c’est qu’une fois que vous avez effectivement appliqué l’une des deux mesures préventives énumérées ci-dessus, le simple redémarrage de Xcode (sans modification de code) devrait faire disparaître l’erreur.

2
George WS

J'ai finalement trouvé la solution. Ajoutez juste "-framework XCTest" à votre cible de test sous Paramètres de construction/autres drapeaux de l'éditeur de liens.

1
CZ54

Ce problème peut également être causé par l'inclusion de catégories ou d'extensions dans la classe de vue de votre cible de test.

0
Brian Croom