Ошибки IBDesignable при добавлении в цель тестов

У меня есть простой подкласс UIButton, который реализует IBDesignable с переменной IBInspectable:

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

Я не использую это в фреймворке, и он работает в Interface Builder, как и предполагалось, однако, как только я добавляю этот подкласс к моей цели Tests, он перестает отображать в реальном времени, и я получаю следующие ошибки:

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

Если я удалю переменные IBDesignable и IBInspectable, ошибки исчезнут - к сожалению, то же самое произойдет и с живым рендерингом в Interface Builder.

Как мне протестировать класс IBDesignable без этих ошибок?


person Adolfo    schedule 25.09.2014    source источник
comment
Есть ли шанс опубликовать на github?   -  person Steve Rosenberg    schedule 05.10.2014
comment
У меня были такие ошибки, когда мой подкласс UIView был реализован в Cocoapod. Перемещение класса UIView в основное приложение заставило его работать.   -  person Graham Perks    schedule 06.11.2014


Ответы (6)


Сначала я подумал, что это какая-то ошибка в Xcode. Ниже приведен обходной путь, который я нашел:

ШАГ 1

Отметьте свой класс и свойства как 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 }
    }
}

ШАГ 2

Импортируйте модуль приложения из модуля «Тесты».

Например, если предположить, что ваше приложение называется MyGreatApp, в вашем 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")
    }
}

Вам не нужно добавлять «Button.swift» в цель «Тесты».

ШАГ 3 (для Swift)

В вашей раскадровке явно выберите модуль MyGreatApp для любых пользовательских классов вместо того, чтобы позволить Xcode использовать текущий модуль.

Interface Builder выбирает основной целевой модуль

person rintaro    schedule 26.09.2014
comment
Добавление public в класс или vars не решило проблему. Перезапуск Xcode всегда очищал ошибки, пока я снова не открывал раскадровку. - person Adolfo; 29.09.2014
comment
Хорошо, я подтвердил, что это не решает проблему. Простите за это. Я отредактировал ответ. - person rintaro; 29.09.2014
comment
Я думаю, что, возможно, упростил свой пример... Я использую кнопку в другом классе, который также тестируется, а также тестирует раскадровку, содержащую классы @IB_. Ситуация, с которой я сталкиваюсь, заключается в том, что мне придется пометить все классы как общедоступные, чтобы импорт модуля работал. Проблема в том, что компилятор просто не может найти @rpath/XCTest.framework/XCTest? - person Adolfo; 30.09.2014
comment
На всякий случай, если вы не видели этот stackoverflow .com/questions/24994593/ - person rintaro; 30.09.2014
comment
Спасибо за информацию. У меня есть кое-что, что происходит с вашими предложениями. Единственная вещь, которая, наконец, заставила его работать в дополнение к объявлению классов и переменных как общедоступных, заключалась в том, чтобы выбрать модуль любых классов, используемых в моей раскадровке, чтобы он был таким же, как моя основная цель - в противном случае Xcode использовал активную цель, которая сломалась, когда я тестируется с использованием тестовой цели. - person Adolfo; 05.10.2014
comment
Я наградил вас наградой и добавил к вашему ответу третий важный шаг по выбору основного целевого модуля для класса в Interface Builder. Еще раз спасибо! - person Adolfo; 05.10.2014
comment
Может быть уместно указать, что последний шаг (добавление модуля) следует выполнять только при использовании swift, поэтому, если вы все еще используете Objective-C, не устанавливайте модуль. - person Edgar; 26.11.2014
comment
К сожалению, у меня это не работает :-( У меня все та же ошибка - person Bartłomiej Semańczyk; 24.06.2015
comment
Шаг 3 был тем, что мне было нужно, после установки одной из моих целей все сработало как надо. - person Fernando Mata; 04.10.2016

Ваш вопрос точно описывает обстоятельства, с которыми я столкнулся. Ошибка также видна в инспекторе атрибутов под вашими собственными атрибутами.

Это обходной путь, который сработал для меня:

Шаг 1 удалите все @IBDesignable и @IBInspectable из исходного кода.

Шаг 2 Вернитесь к конструктору интерфейсов. Ошибка все еще там.

Шаг 3 Перезапустите XCode, перестройте свой проект. Ошибки должны исчезнуть.

Шаг 4 снова добавьте все @IBDesignable и @IBInspectable в исходный код.

После этих шагов я смог продолжить свой проект без каких-либо проблем.

Моя теория, почему это работает, заключается в том, что построитель интерфейса кэширует некоторые вещи, которые не удаляются (и перестраиваются позже), когда вы делаете Project -> Clean.

Другой ответ (импорт вашего основного модуля в тестовый модуль) - хорошая идея, и он решил некоторые неприятные проблемы для меня в прошлом, но не этот.

person Gerd Castan    schedule 01.03.2015
comment
В дополнение к очистке вы пытались вручную удалить папку Derived Data, чтобы устранить свои ошибки? - person Adolfo; 02.03.2015
comment
Больше не могу это проверить, потому что я не знаю, как намеренно создать эту проблему. - person Gerd Castan; 06.03.2015
comment
У меня была эта проблема, я удалил Derived Data, и ошибка осталась. Затем я последовал указаниям Герда, и ошибка исчезла. Я согласен с теорией Герда о том, что IB кэширует данные где-то, что не очищается, и теперь добавлю, что они также находятся где-то за пределами производных данных. Если кто-нибудь знает, где IB кеширует информацию, сообщите нам, чтобы мы могли удалить его напрямую в подобных ситуациях! :) - person George WS; 05.01.2016
comment
Вам, вероятно, также необходимо удалить ~/Library/Caches/com.apple.dt.Xcode, см. эту ссылку для получения более подробной информации stackoverflow.com/a /6247073/539149 Я рекомендую сохранять символические ссылки в такие общие места, как это, или писать сценарий applescript или shell для их удаления. - person Zack Morris; 26.01.2016
comment
Работал и для меня. Спасибо. - person andynil; 04.10.2016

Решение очень простое. Вам нужно удалить тестовую цель и создать ее заново с самого начала. Когда я переместил проект на Xcode 7, я получил предупреждение о том, что моя тестовая цель повреждена. Поэтому я решил установить его еще раз. ЭТО РАБОТАЛО!.

Кроме того, вы не прикрепляете свои раскадровки и даже не какой-либо класс к своей тестовой цели. Пожалуйста, не делайте так:

введите здесь описание изображения

Вместо этого сделайте это следующим образом:

введите здесь описание изображения

Итак, просто удалите любой файл из вашей тестовой цели (включая классы с @IBDesignables), затем, если вам нужен доступ к вашим классам в вашей тестовой цели, просто используйте @testable import MyApp:

введите здесь описание изображения

Он работает, и все ошибки с IBDesignables исчезнут. Наслаждаться:-)

person Bartłomiej Semańczyk    schedule 26.06.2015

В чем причина?

Эта ошибка появляется, когда происходят две вещи:

  1. Вы включаете любой файл, содержащий @IBDesignable или @IBInspectable, в свою тестовую цель.
  2. Вы открываете файл .storyboard или .xib (содержащий ваши проектируемые/проверяемые представления).

Как этого избежать?

Или:

  1. Не включайте файлы, содержащие @IBDesignable или @IBInspectable, в тестовую цель. (Если вы просто тестируете несколько изолированных файлов моделей, они могут оставаться членами вашей тестовой цели.)
  2. Удалите все файлы вашего приложения из тестовой цели (как показано в ответе Бартломиея) и вместо этого импортируйте файлы вашего приложения. в тестовый файл (например, @testable import MyAppподробнее см. здесь). Это передовой опыт, позволяющий продолжить тестирование проектируемых/проверяемых представлений, а также любого кода модели в приложении.

Как я могу решить эту проблему, если она уже произошла?

Досадная вещь с этой ошибкой заключается в том, что она не исчезает автоматически после решения проблемы, возможно, потому, что IB может кэшировать что-то как Герд предлагает в своем ответе.

Я обнаружил, что после того, как вы фактически выполнили одну из двух предупредительных мер, перечисленных выше, простой перезапуск Xcode (без изменения какого-либо кода) должен устранить ошибку.

person George WS    schedule 05.01.2016

Я наконец нашел решение. Просто добавьте «-framework XCTest» в свою тестовую цель в разделе «Настройки сборки» / «другие флаги компоновщика».

person CZ54    schedule 25.09.2015

Эта проблема также может быть вызвана включением любых категорий или расширений в класс представления в тестовую цель.

person Brian Croom    schedule 29.04.2016