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...:/
Ответы
Ответ 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
У меня была эта ошибка, когда у меня две цели. Один с моим основным проектом и другой с целью, где я держу классные классы (для более быстрой сборки).
Проблема заключалась в том, что в раскадровке отсутствовал модуль.
![введите описание изображения здесь]()