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

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

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", то эти настраиваемые свойства не отображались бы в инспекторе атрибутов, верно? Но когда Интерфейсный Разработчик пытается применить эти атрибуты к представлению, он снова думает, что класс представления является "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.

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


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

11 ответов

Решение

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

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

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

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

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

Нажав кнопку "Показать", я получу предупреждения:

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

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

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

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

Тем не менее, до этого момента все, что я делал, было вещами, с которыми я никогда не шутил дома. Дома это просто сработало. Поэтому я включил "Автоматически обновлять представления" и создал "Четвертое представление" для тестирования - опять же, идентично первым трем.

После изменения класса представления на "Fourth View" ярлык designables на короткое время произнес "Обновление", а затем, наконец, сказал "Обновлен":

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

чистка DerivedData и предупреждение ушло.

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

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

а также

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

Решил мою проблему, поставив модуль с именем CheckboxButton, как показано ниже:

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

Incase любой другой сталкивается с ошибкой 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">

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

Ответ Дэйва Томаса, приведенный выше, дал мне (обратное) решение, когда не другие (Derived Data, Editor > Refresh) сделали, но ради ясности на случай, если люди не уверены, где редактировать XML... вы не Т надо!

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

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

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

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

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

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

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

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

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

У меня возникла та же проблема, и мне пришлось изменить 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
    }
}
Другие вопросы по тегам