Ответ 1
После публикации этого вопроса я узнал, что @IBDesignable не работает для расширений класса. Вы можете добавить тег, но он не имеет никакого эффекта.
Для тех, кто не знает, о чем я говорю, Xcode 6.0 добавил новые функции, IBDesignable и IBInspectable.
Когда вы помечаете свои пользовательские представления свойствами IBInspectable, эти свойства отображаются в Инспекторе атрибутов в IB.
Аналогично, когда вы помечаете пользовательский подкласс UIView с IBDesignable, Xcode компилирует ваши представления и вызывает код для рендеринга ваших объектов вида прямо в окне Xcode, чтобы вы могли видеть, как они выглядят.
Метод добавления атрибутов IBDesignable и IBInspectable к пользовательским представлениям почти идентичен в Swift и Objective-C. Свойства IBInspectable отображаются в инспекторе атрибутов интерфейса Builder независимо от того, какой язык вы используете для их определения.
Я создал категорию UIView в Objective-C и расширение UIView в Swift, которое поддерживает свойства borderWidth, cornerRadius, borderColor и layerBackgroundColor слоя, лежащего в основе представления, как свойства представления. Если вы измените свойство, расширение/категория делает преобразование по мере необходимости и перенаправляет изменение на слой.
Часть IBInspectable отлично работает. Я вижу и могу установить новые свойства в инспекторе атрибутов IB.
Я мог бы поклясться, что на прошлой неделе атрибут IBDesignable в моей категории категорий/расширении тоже работал, и я мог видеть свою собственную визуализацию категорий UIView в IB с изменением атрибутов слоя. На этой неделе он не работает.
Был ли я галлюцинацией?
Можно ли использовать категории/расширения существующих системных классов свой пользовательский интерфейс в Interface Builder, когда они настроены с помощью IBDesignable?
После публикации этого вопроса я узнал, что @IBDesignable не работает для расширений класса. Вы можете добавить тег, но он не имеет никакого эффекта.
@IBDesignable работать с расширением UIView только в пользовательском классе. Например. UILabel является подклассом UIView по умолчанию. Он не будет работать там, но если вы создадите собственный класс под названием MyUILabel для подкласса UILabel. присвойте классу MyUILabel метке, над которой вы работаете. Тогда ваш угловой радиус в расширении UIView будет работать с этим MyUILabel. (Я думаю, что в первую неделю он работает для вас, потому что вы имеете дело с каким-то специальным классом.)
Я сделал эту работу для своего варианта использования, имея один @IBDesignable UIView, который я установил как верхний вид в моем контроллере представления. В моем конкретном случае использование стилей ClassyKit видимо в интерфейсе Builder в представлении UIKit по умолчанию, но для этого не требуется подкласс, и он отлично работает.
Вот пример того, как вы могли настроить его:
// in Interface Builder set the class of your top view controller view to this
@IBDesignable class DesignableView: UIView {
}
extension UIView {
open override func prepareForInterfaceBuilder() {
subviews.forEach {
$0.prepareForInterfaceBuilder()
}
}
}
extension UILabel {
// just an example of doing something
open override func prepareForInterfaceBuilder() {
layer.cornerRadius = 8
layer.masksToBounds = true
backgroundColor = .red
textColor = .green
}
}
Мне удалось заставить его работать с кодом ниже, но побочным эффектом является то, что несколько раз агент IB в раскадровке падает, потому что он должен обновлять слишком много элементов интерфейса. Перезапуск Xcode временно устраняет проблему до следующего сбоя. Возможно, что проблема OP обращена к
@IBDesignable
extension UIView
{
@IBInspectable
public var cornerRadius: CGFloat
{
set (radius) {
self.layer.cornerRadius = radius
self.layer.masksToBounds = radius > 0
}
get {
return self.layer.cornerRadius
}
}
@IBInspectable
public var borderWidth: CGFloat
{
set (borderWidth) {
self.layer.borderWidth = borderWidth
}
get {
return self.layer.borderWidth
}
}
@IBInspectable
public var borderColor:UIColor?
{
set (color) {
self.layer.borderColor = color?.cgColor
}
get {
if let color = self.layer.borderColor
{
return UIColor(cgColor: color)
} else {
return nil
}
}
}
}
Вот почему я пытаюсь добавить предложение where, чтобы уменьшить подклассы, которые должны расширить эту функциональность: Общий IBDesginables расширение UIView
Этот блок кода работает хорошо для меня.
import UIKit
public extension UIView {
@IBInspectable public var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
}
ПРИМЕЧАНИЕ Это может не сработать при импорте из фреймворка. Сейчас я пытаюсь выяснить причину.