20

对于那些不知道我在说什么的人,Xcode 6.0 添加了新功能,IBDesignable 和 IBInspectable。

当您使用 IBInspectable 属性标记自定义视图时,这些属性会显示在 IB 的 Attributes Inspector 中。

同样,当您使用 IBDesignable 标记自定义 UIView 子类时,Xcode 会编译您的视图并调用代码以直接在 Xcode 窗口中呈现您的视图对象,以便您可以看到它们的外观。

将 IBDesignable 和 IBInspectable 属性添加到自定义视图的技术在 Swift 和 Objective-C 中几乎相同。IBInspectable 属性出现在 Interface Builder Attributes Inspector 中,无论您使用哪种语言来定义它们。

我在 Objective-C 中创建了一个 UIView 类别,并在 Swift 中创建了 UIView 的扩展,将视图底层的borderWidth、cornerRadius、borderColor 和layerBackgroundColor 属性提升为视图的属性。如果更改属性,扩展/类别会根据需要进行类型转换并将更改转发到图层。

IBInspectable 部分效果很好。我看到并可以在 IB 属性检查器中设置新属性。

我本可以在上周发誓,我的视图类别/扩展上的 IBDesignable 属性也在工作,我可以在 IB 中看到我的自定义 UIView 类别呈现,它的图层属性已更改。这周它不工作。

我是不是产生了幻觉?

现有系统类的类别/扩展是否可以在使用 IBDesignable 设置时在 Interface Builder 中绘制其自定义 UI?

4

5 回答 5

26

自从发布这个问题以来,我了解到 @IBDesignable 不适用于类扩展。您可以添加标签,但它没有效果。

于 2015-11-08T12:49:33.547 回答
7

我能够使用下面的代码使其工作,但副作用是有时故事板中的 IB 代理会崩溃,因为它必须刷新太多的 UI 元素。重新启动 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子句来减少应该扩展此功能的子类: Generic IBDesginables UIView extension

于 2017-06-22T17:07:56.173 回答
1

@IBDesignable 仅在自定义类中与 UIView 扩展一起使用。例如。UILabel 是 UIView 的默认子类。它不会在那里工作,但如果你创建一个名为 MyUILabel 的自定义类继承 UILabel。将 MyUILabel 类分配给您正在处理的标签。然后你在 UIView 扩展中的圆角半径将适用于这个 MyUILabel。(我想它对你有用的第一周是因为你正在处理一些自定义类。)

于 2016-07-20T14:11:16.023 回答
1

通过在我的视图控制器中设置一个@IBDesignable UIView 作为顶视图,我已经为我的用例完成了这项工作。我的特定用例是在默认 UIKit 视图的 Interface Builder 中使 ClassyKit 样式可见,而不必为此进行子类化,并且效果很好。

这是一个如何设置它的示例:

// 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
    }
}
于 2016-10-29T16:42:57.903 回答
-4

这个代码块对我来说效果很好。

import UIKit

public extension UIView {
    @IBInspectable public var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }
}

注意从框架导入时它可能不起作用。我现在正试图找出原因。

于 2015-09-04T08:13:43.453 回答