IB_DESIGNABLE, IBInspectable - построитель интерфейса не обновляется


91

У меня есть следующий набор кода:

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

(Для справки Swift эта проблема также возникала с кодом 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
        }
    }
}

Я добавил UIViewк контроллеру представления на раскадровке и установил для его подкласса значение CustomView.

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

Это добавляет строку «Designables». Он застрял на «Обновление», а во всплывающей подсказке написано «Ожидание сборки». Он никогда не меняется с этого статуса.

Когда я перехожу к проверке атрибутов, я могу установить следующие IBInspectableсвойства:

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

И после установки они также отображаются в «Пользовательских атрибутах времени выполнения»:

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

Однако статус «Designables» никогда не выходит за пределы «Updating» с той же подсказкой (я пробовал строить Cmd + B несколько раз, ничего не изменилось).

Более того, когда я устанавливаю IBInspectableсвойства, я получаю предупреждение для каждого из них:

IBDesignables - Игнорирование определенного пользователем атрибута времени выполнения для ключевого пути "borderColor" в экземпляре "UIView" ... этот класс не соответствует кодированию "ключ-значение" для ключевого borderColor.

Скриншот сгенерированных предупреждений:

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


Я знаком с проблемами, связанными с кодированием "ключ-значение", и в целом знаю, как их решать ... но я не понимаю, как решить эту проблему здесь. Согласно инспектору идентичности представления, представление является «CustomView» (а не обычным «UIView», у которого нет этих свойств). И если бы представление не было «CustomView», то эти настраиваемые свойства не отображались бы в инспекторе атрибутов, верно? Но когда Interface Builder пытается применить эти атрибуты к представлению, он снова начинает думать, что класс представления - «UIView», и не может применить атрибуты.

Любая помощь? Пожалуйста, дайте мне знать, если я упустил некоторые важные детали, но чего бы это ни стоило, я в точности следовал этому руководству (кроме ObjC vs Swift). Также стоит отметить, что я следовал этому руководству точно на другой машине, и он работал как шарм (я собирался опубликовать этот пост вчера вечером, но компьютер, на котором я был тогда, не имел этой проблемы).


На основании комментариев было высказано предположение, что, возможно, .mфайл не включен, и это может быть причиной проблемы. Я подумал, что, конечно, я бы изо всех сил старался реализовать этот сценарий, но все равно проверил.

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

Когда я впервые начал это делать, я понимал, что IB_DESIGNABLEклассы должны быть частью другой UIKitструктуры. Итак, на этом первом снимке экрана вы можете видеть, что я установил фреймворк CustomViews, который имеет один класс CustomView. Вы также увидите, что я также создал файл OtherView, идентичный CustomView, за исключением того, что он не находится в отдельной структуре. Однако идентичная проблема сохраняется в раскадровке между обоими классами.

Здесь у нас есть снимок экрана, показывающий, что CustomView.mон включен для сборки с CustomViewsфреймворком:

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

Между тем на следующем снимке экрана показано несколько вещей:

  • CustomViews.framework надлежащим образом включен в основной проект.
  • OtherView.mтакже включен в качестве источника компиляции, поэтому, даже если что-то не так CustomView, OtherViewдолжно работать, однако он генерирует идентичные ошибки.
  • Main.storyboardи LaunchScreen.xibотображаются красным. Я понятия не имею, почему, и не имею ни малейшего представления о том, почему это LaunchScreen.xibдолжно быть (я не касался этого файла), хотя я могу сказать, посмотрев другие проекты, Main.storyboardтакже отображается красным для этих проектов, и я ничего не делаю с IB_DESIGNABLEили IBInspectableтам.

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


Я пробовал и пробовал это несколько раз. Он работает каждый раз на моем компьютере дома - дома я не могу воспроизвести проблему, описанную в этом вопросе. На работе никогда не работает. Проблема, описанная в этом вопросе, возникает каждый раз.

Оба компьютера - Mac Minis, купленные в этом году новыми (не новые модели, модель конца 2012 года). Оба компьютера работают под управлением OS X Yosemite 10.10. Оба компьютера работают под управлением Xcode версии 6.1. Дома сборка (6A1052d). Сегодня утром я могу подтвердить, что на обоих компьютерах установлены идентичные сборки Xcode.

Другие предположили, что это может быть плохая оперативная память. Мне это кажется невероятным. Я несколько раз перезапускал проект, несколько раз перезагружал компьютер. Мне кажется, если бы на компьютере примерно 6 месяцев была плохая оперативная память, я бы увидел другие проблемы, и эта проблема была бы менее последовательной. Но эта проблема сохраняется, несмотря на многократный перезапуск всего проекта с нуля и полный перезапуск на компьютере.


Следует отметить, что если я действительно компилирую и запускаю этот проект, пользовательское представление со IBInspectableсвойствами фактически отображается так, как я ожидаю, что раскадровка отобразит его. Я полагаю, что это было бы так даже без директив IB_DESIGNABLEи IBInspectable, поскольку они создаются как определяемые пользователем атрибуты времени выполнения.


Что ж, это была просто идея. Я удалил CustomView.m из цели, а затем получил аналогичные предупреждения при запуске приложения.
Martin R

Это похоже на настоящий гремлин, учитывая ваше сравнение с, казалось бы, идентичной машиной (которая чем-то отличается). Вы пробовали публиковать сообщения на форумах разработчиков? Кажется, что вы летите вслепую без дополнительной информации, и ваш процесс кажется аргументированным и рациональным. Предупреждение о «сборке» может не значить слишком много, поскольку Xcode изобилует вводящими в заблуждение сообщениями об ошибках. Однако для удовольствия вы попробовали Редактор -> «Отладка выбранного вида», верно? (Возможно, не сработает, но стоит проверить работоспособность). Кроме того, что-нибудь отображается в приложении консоли (ведение журнала)?
Крис Коновер

У меня такая же проблема. Майны с одним файлом xib, содержащим IB_DESIGNABLE. Однако, проверяя мои настройки, у меня уже есть автоматическое обновление, и теперь я пробовал обновлять вручную, сначала очищать производные данные и т. Д. Пока ничего не работает. Странно то, что у меня этот элемент управления работал нормально, а потом он остановился. И я не думаю, что изменил какой-либо код между ними. Псих.
drekka

Показывал предупреждения, как указано выше. Теперь создан второй класс с кодом, скопированным из исходного IB. Этот класс работает отлично, и когда я вернулся к исходному нерабочему классу, он теперь работает нормально. Из этого я пришел к выводу, что где-то есть некоторый кеш (не в производных данных), который не очищается до тех пор, пока исходный дизайн ib не будет заменен на другой дизайн ib. Переход на UIView, похоже, не очищает этот кеш. Только еще одна иб проектируемая. Иди и
разберись

Ответы:


75

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

  • Автоматически обновлять просмотры
  • Обновить все представления

Я щелкнул «Обновить все представления», и после того, как Xcode немного подумал, внезапно раскадровка отображала мое представление, как и ожидалось (правильно применяя мои IBInspectableсвойства).

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

Затем я снова прошел весь процесс, чтобы убедиться, что это решение.

Я создал новый класс ThirdView. Опять же, этот класс идентичен другим. Я изменил класс своего представления на ThirdViewи на этот раз получил что-то немного другое:

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

Нажав «Показать» мне на предупреждения:

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

На этот раз новый:

Использование класса UIView для объекта с настраиваемым классом, потому что класс ThirdView не существует.

На самом деле это не более полезно, чем то, что уже существовало. Кроме того, теперь три других предупреждения странным образом удвоились до шести.

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

Тем не менее, до этого момента все, что я делал, было тем, с чем я никогда не связывался дома. Дома просто работало. Итак, я включил «Автоматически обновлять представления» и создал для тестирования «FourthView» - опять же, идентичный первым трем.

После изменения класса представления на «FourthView» метка назначаемых элементов на короткое время сказала «Обновление», а затем, наконец, произнесла «В актуальном состоянии»:

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

Итак, я проверил свой компьютер дома. «Автоматически обновлять просмотры» включен на компьютере, который всегда работал. Он был выключен на компьютере, которого не было. Я не помню, чтобы касался этого пункта меню. Я даже не могу сказать вам наверняка, существовал ли он до Xcode 6. Но именно этот вариант имел значение.


TL; DR, если у вас возникла та же проблема, что описана в вопросе, убедитесь, что "Автоматически обновлять представления" включен (или вручную "Обновлять все представления", когда вам нужно обновление в IB):

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


2
На самом деле я искал, как его выключить, поскольку он продолжает рендеринг в фоновом режиме, что делает старые MacBook очень медленными. Благодарность!
Departamento B,

Это может временно разрешить проблему, но посмотрите ответ от @ Martin-Gilles Lavoie
Ashley Mills,

22

У меня есть еще несколько деталей, из-за которых ваши классы IBDesignable могут не загружаться.

Выберите проблемную раскадровку / xib, где должны отображаться ваши пользовательские представления.

В области навигатора перейдите к навигатору отчетов в рабочем пространстве / проекте XCode.

В меню редактора XCode нажмите (как упомянул nhgrif), пункт «Обновить все представления». Это заставит IB запустить компиляцию для целой кучи вещей, которых вы, я уверен, не ожидаете.

В навигаторе отчетов щелкните «По группе», чтобы отфильтровать содержимое, и посмотрите раздел «Интерфейсный редактор». Вы увидите, что для загрузки пользовательского фреймворка представлений IBDesignable он скомпилирует МНОГО вещей. Если какие-либо из этих целей НЕ компилируются, такие как (возможно, устаревшие) цели модульного тестирования (даже если они полностью не связаны с кодом, который загружает эти представления или раскадровку), то IB не сможет загрузить вашу dll.

В моем случае IB попытался скомпилировать 8 целей, в том числе 4 юнит-тестов, которые не обновлялись с момента недавних изменений рефакторинга, над которыми мы работали.

Большинство изменений / исправлений кода, которые я сделал, чтобы IB правильно загружал и отображал мои таможенные представления, которые не связаны или даже не связаны с этими классами, и при этом он никогда не загружал бы раскадровку в ходе выполнения этих модульных тестов. Тем не менее, IB зависел от компиляции всего рабочего пространства, чтобы он работал.


Привет, а как мне остановить попытки IB загружать и отображать представления, не связанные с этими классами или не связанные с ними?
Ханна Карни,

Я предполагаю, что это связано с зависимостями заголовков. Если проектируемые классы соприкасаются с другими классами, в тот момент, когда заголовок виден, он построит эти связанные реализации. Apple играет с исходным кодом графа зависимостей в XC7GM, который совершенно не работает в нашем проекте из-за сбоя XCode при построении графа. Следующие 7.1beta не обнаруживают проблемы. Наша автоматизированная система сборки на данный момент все еще зависит от версии 6.4, поэтому мы не исследовали, как решить эту проблему в XC6.4. Мы сразу перейдем к 7.1GM.
Мартин-Жиль Лавуа,

Если у вас есть несколько целей / проектов, то это абсолютно правильный ответ и действительно решает проблему - ВСЕ цели должны быть построены чисто, я даже не знал, что в навигаторе отчетов есть раздел «Интерфейсный редактор»! Все остальные ответы, которые я видел, в основном представляют собой размахивание руками, которые могут временно исправить это, но это окончательное решение. Отлично сработано.
Эшли Миллс

3
Итак, исходя из этого, мы можем сделать вывод, что атрибут IB_DESIGNABLE - это полная чушь и трата времени. Просто избегайте его использования.
m8labs

IB_DESIGNABLE не имеет ничего общего с проблемой и решением, перечисленными выше. Это просто отметка NO-OP для IB, чтобы обнаружить полезные вещи. Вам просто нужно поддерживать в доме чистоту.
Мартин-Жиль Лавуа,

22

Просто быстрый совет для всех, кто сталкивается с этой проблемой: не забудьте указать тип переменной.

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

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

6

У меня было такое же предупреждение, Ignoring user defined runtime attribute for key path ..хотя я абсолютно уверен, что не сделал ничего плохого с моим пользовательским классом представления IBDesignable.

Оказалось, что в моем случае это связано с кешем Xcode.

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

Очистите, DerivedDataи предупреждение исчезнет.


1
Ярлык в XCode для достижения того же результата: ⌘⇧K
Mojo66

@ Mojo66 Я считаю, что чистая сборка отличается от очистки папки DerivedData. Конечно, иногда чистая сборка достаточно хороша для решения определенных проблем с кешированием Xcode.
samwize

@ Mojo66, вы, наверное, имели в виду ⌘⌥⇧K (cmd + alt + shift + K)
tzaloga

5

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

В исходном коде раскадровки скрыто свойство customModule.

Например, у меня был класс ForwardArrow внутри отдельного фреймворка, который я случайно добавил к своей основной цели.

Таким образом, XML для некоторых представлений закончился как customClass = "ForwardArrow" customModule = "MainTargetNameWasHere"

Когда я удалил их из основной цели в сборке, раскадровка не обновила MainTargetNameWasHere до CustomViews, который является фреймворком, в котором он был расположен, и начала выдавать эту ошибку, класс не найден.

Итак, TLDR; Убедитесь, что если ваш IBDesignable находится в другой структуре, что для атрибута customModule xml в вашей раскадровке установлено правильное значение. А если его там совсем нет, добавьте.

Пример из моего источника:

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

1
Черт возьми, это уже целый день сводит меня с ума. Какая неприятная маленькая ошибка.
GoldenJoe

5

В качестве моего примера я использовал CheckboxButton через модуль, и графика флажка никогда не отображается в раскадровке, в то время как у меня возникли те же проблемы, которые описаны в вопросе здесь:

предупреждение: IB Designables: использование класса UIView для объекта с настраиваемым классом, потому что класс CheckboxButton не существует

а также

предупреждение: IB Designables: игнорирование определенного пользователем атрибута времени выполнения для ключевого пути "checkColor" в экземпляре "UIView". Произошла ошибка при попытке установить его значение: [setValue: forUndefinedKey:]: этот класс не соответствует кодированию значения ключа для ключа checkColor.

Способ решения моей проблемы заключался в предоставлении модуля с именем CheckboxButton, как показано ниже:

Примечание: вы должны заменить CheckboxButton на любое имя используемого модуля.


4

Я лично решил эту проблему, используя кнопку «-», чтобы удалить контент из моего инспектора личности. Когда вы удаляете настраиваемые классы, изменяете содержимое в IB, а затем добавляете новый настраиваемый класс, проектируемые элементы в инспекторе идентичности не удаляются, и это вызывало у меня эту ошибку. Просто удалите все и восстановите.введите описание изображения здесь


Я сделал именно то, что вы сказали, и это решило мою проблему. Все предыдущие решения, представленные здесь, не прошли. Большое спасибо. ; o)
XLE_22

@ XLE_22 иногда ответы, на которые никто не смотрит, решают ее, а? :)
HannahCarney

У меня возникла проблема, когда я переименовал свойство IBInspectable в нескольких своих xib. После этого у меня появилось множество предупреждений о том, что XCode не может найти переименованное свойство. Удаление свойства из инспектора удостоверений решило мою проблему.
WBuck

1

Я знаю, что на это есть ответ, но вот еще один опыт.

У меня возникли некоторые проблемы, не связанные с этой проблемой, но в процессе я удалил @IBInspectable из варов своего класса и удалил атрибуты из инспектора идентичности (alt-apple-3).

После исправления (кода) проблемы с компонентом я обновлял все множество раз, но все еще не было атрибутов в инспекторе идентичности.

В конце концов, я заметил, что они вернулись, но только в инспекторе атрибутов (alt-apple-4) . Как только я добавил им значения, они снова появились в инспекторе личности


1

Приведенный выше ответ Дэйва Томаса дал мне (обратное) решение, хотя не из других (Производные данные, Редактор> Обновить), но для ясности на случай, если люди не уверены, где редактировать XML ... вы не делаете ' не нужно!

  1. В вашем файле раскадровки выберите проблемный вид
  2. На правой боковой панели выберите вкладку Identity Inspector (третий вариант слева).
  3. У вас будет собственный класс, который уже должен быть установлен, и Module. Для меня это было пусто, и я получал те же ошибки, что и OP. Я установил имя Moduleсвоего проекта и БАМ - он начал работать после восстановления!

0

Я только что пробежался по этой проблеме. Я безуспешно пробовал все перечисленные здесь и в других местах. Это раскадровка, которая отлично работала всегда, и она внезапно перестала работать из-за проблемы «Игнорирование определяемого пользователем атрибута времени выполнения ...».

По какой-то причине удаление этого кода из одного из моих IBDesignable исправило его:

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

удаление этого привело к исчезновению всех предупреждений, даже в других объектах IBDesignable. Понятия не имею, почему этот один шаг исправил его, но, возможно, это поможет и кому-то другому.


3
вам не хватает звонка на ужин здесь
RolandasR

0

У меня была та же проблема, и мне пришлось изменить cornerRadius и BorderWidth на String, а затем преобразовать их в CGFloat, это было единственное решение для меня, чтобы иметь возможность изменять значения и видеть изменения в построителе интерфейса.

@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
    }
}

Я думаю, что IBInspectable может работать только с определенными типами, поэтому, возможно, вам нужно было бы использовать Floatвместо этого CGFloatи приводить его вместо этого
Fonix
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.