Подтвердить что ты не робот

UIButton с IB_DESIGNABLE вызывает предупреждение атрибута времени выполнения и не отображается в Interface Builder

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

Следующее предупреждение записывается в журнал и нет предварительного просмотра моего кода в drawRect:

warning: IB Designables: Ignoring user defined runtime attribute for key path "spacingBetweenLabelAndImage" on instance of "UIButton". Hit an exception when attempting to set its value: [<UIButton 0x7f9278591260> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key spacingBetweenLabelAndImage.

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

Вот код меню, который перестраивает кнопку и название:

#import "HamburgerButton.h"

IB_DESIGNABLE
@interface HamburgerImageButton : HamburgerButton

@property IBInspectable CGFloat spacingBetweenLabelAndImage;

@end

Реализация:

#import "HamburgerImageButton.h"

@implementation HamburgerImageButton

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    CGSize imageSize = self.imageView.frame.size;
    CGSize titleSize = self.titleLabel.frame.size;

    // Move the label left and the image right by half the width
    CGFloat leftInset = titleSize.width / 2;
    CGFloat rightInset = imageSize.width / 2;

    CGFloat halfSpacing = self.spacingBetweenLabelAndImage == 0 ? 0 : self.spacingBetweenLabelAndImage / 2;

    CGFloat topInset = imageSize.height / 2 + halfSpacing;
    CGFloat bottomInset = titleSize.height / 2 + halfSpacing;

    UIEdgeInsets imageInsets = UIEdgeInsetsMake(-bottomInset, leftInset, bottomInset, -leftInset);
    UIEdgeInsets titleInsets = UIEdgeInsetsMake(topInset, -rightInset, -topInset, rightInset);
    self.imageEdgeInsets = imageInsets;
    self.titleEdgeInsets = titleInsets;
}

@end

Вы, наверное, заметили, что он наследует HamburgerButton. Эта основная кнопка гамбургера не имеет изображения, и она только рисует рамку вокруг кнопки. Эта основная кнопка гамбургера имеет точно такую ​​же проблему: она не рисует границу в drawRect в IB, и у нее одинаковые ошибки. Вот этот код для полноты:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface HamburgerButton : UIButton

@property IBInspectable CGFloat borderWidth;
@property IBInspectable UIColor *borderColor;

@end

Реализация:

#import "HamburgerButton.h"
#import <QuartzCore/QuartzCore.h>

@implementation HamburgerButton

- (void)copyInspectables {
    self.layer.borderWidth = self.borderWidth;
    self.layer.borderColor = self.borderColor.CGColor;
}

- (void)drawRect:(CGRect)rect {
    [self copyInspectables];
}

@end

Я действительно не понимаю, почему он просто предупреждает и ничего больше. Я действительно не изменил то, что сделал. Я проверил раскадровку, это iOS 7 и выше, предназначенный для запуска в Xcode 6 (последний).

Он жалуется, что не смог найти это значение в UIButton и немного странно, потому что я подклассифицировал его.


Обновление: Поэтому я все изменил, и это сработало. Теперь он снова дергается, не меняя ничего другого. Я думаю, что есть ошибка в Xcode 6.1...:/

4b9b3361

Ответ 1

Я активно работаю с Live Views с момента его внедрения и, как и многие новые функции в Xcode, изначально имеет некоторые недостатки. Тем не менее мне это очень нравится, и я надеюсь, что он будет улучшен в более новых версиях.

Причина:

Живые представления работают с свойствами @property, которые получают специальный тег IB_Designable, который даст дополнительные атрибуты класса UI, к которым он может обратиться, с помощью атрибутов User Defined Runtime, которые будут установлены с помощью Attributes Inspector. Вы увидите, что все эти свойства также существуют в Identity Inspector. Основная причина проблемы заключается в том, что она больше не может сопоставлять эти атрибуты, определенные пользователем, для открытых свойств.

Как только вы откроете раскадровку или xib, которая использует IB_Designable, Xcode будет перекомпилировать экран при каждом изменении, если вы включили "Автоматическое обновление просмотров". Так как ваш код влияет на ваш пользовательский интерфейс, это не должно быть изменением в Interface Builder как таковом.

С более простыми проектами на более быстрых машинах это работает довольно хорошо в большинстве случаев. С более крупными проектами, которые также имеют больше IB_Designable, процессор просто не имеет достаточной емкости, чтобы идти в ногу с вами, и вы получите некоторую ошибку тайм-аута при рендеринге пользовательского интерфейса. Это причина предупреждения : IB Designables: игнорирование пользовательского атрибута времени выполнения для ключевого пути "spacingBetweenLabelAndImage" в экземпляре "UIButton". Удалите исключение при попытке установить его значение: [setValue: forUndefinedKey:]: этот класс не является ключевым значением, совместимым с кодировкой для ключевого пробелаBetweenLabelAndImage..

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

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

Решение:

Нам нужно убедиться, что ваш пользовательский класс класса снова компилируется, чтобы свойства могли быть успешно установлены с помощью Interface Builder

  • В режиме раскадровки перейдите в "Редактор" в верхнем меню панели
  • снимите флажок "Автоматически обновлять представления", если он все еще включен
  • Закройте все вкладки раскадровки
  • Восстановить проект
  • Исправить все ошибки сборки, если есть
  • Откройте раскадровку.
  • Снова перейдите в "Редактор" и нажмите "Обновить все представления"

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

После комментариев, приведенных sunkas: всегда хорошая идея очистить ваше решение в случае каких-либо странных проблем, которые сохраняются.

Ответ 2

Как я лично исправил это:

В инспекторе идентификации в User Defined Runtime Attributes я заметил, что у меня был старый элемент IB_Inspectable, который я удалил из своего кода, но он все еще был там. Удаление этой кнопки с помощью этой кнопки избавилось от этой ошибки.

identityinspector

Ответ 3

Попробуйте изменить объявление "CGFloat" для spacingBetweenLabelAndImage в "NSNumber".

Насколько я знаю, вы не можете вызвать "setValue:" в переменной типа C.

Изменение объявления "spacingBetwenLabelAndImage" на NSNumber также потребует также изменения кода:

CGFloat halfSpacing = self.spacingBetweenLabelAndImage == 0 ? 0 : self.spacingBetweenLabelAndImage / 2;

может стать чем-то вроде:

CGFloat halfSpacing = (self.spacingBetweenLabelAndImage ? ([self.spacingBetweenLabelAndImage floatValue] / 2) : 0.0);

(Я не уверен на 100%, если это идеальный перевод первой строки, но я хотел показать, как получить floatValue из NSNumber)

Ответ 4

Я использовал метод Departamento B, но он действительно не работал. Однако я исправил свою проблему 1. Выбор багги-представлений из доски объявлений 2. Нажатие (Редактор - Отладка выбранного вида) Надеюсь, что это поможет

Ответ 5

Если вы уверены, что правильно настроили все сеттеры, и если вы импортировали некоторые другие SDK в свой проект, и вы получаете эту проблему, установите флажок "Связанные структуры и библиотеки" в "Целевая задача".

После правильной привязки некоторых фреймворков SDK ошибка исчезла.

Ответ 6

У меня была аналогичная проблема, но я фактически удалил свойство из класса, и Interface Builder все еще жаловался на недостающее свойство, жесткое.

Пробовал много вещей, таких как чистка, перестройка... Но ничего не работало!

Что действительно было решено, щелкнул правой кнопкой мыши в файле раскадровки, выбрав "Открыть как", а затем "Исходный код". Это открыло XML-контент раскадровки в редакторе, и я смог найти ссылки на недостающее свойство, пока не нашел раздел:

<userDefinedRuntimeAttributes>
    <userDefinedRuntimeAttribute... keyPath="My Missing Property Name">
    ...
</userDefinedRuntimeAttributes>

После удаления всего раздела я сохранил файл и обновил представление в Interface Builder. Теперь все предупреждения ушли!

Ответ 7

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

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