IB Designables:无法呈现和更新自动布局状态...代理崩溃

IB Designables: Failed to render and update auto layout status ...The agent crashed

当我在 IBDesignable 中包含以下代码时,界面生成器代理崩溃 class。

    self.backgroundColor = UIColor.mooButtonBackgroundColor

颜色的表示形式为:

@nonobjc class var mooButtonBackgroundColor : UIColor {
    UIColor(named: "Color.Button.Background")!   // 0.129, 0.490, 0.851, 1
}

但是,如果我将返回的值更改为:

@nonobjc class var mooButtonBackgroundColor : UIColor {
    .green //UIColor(named: "Color.Button.Background")!   // 0.129, 0.490, 0.851, 1
}

一切正常。

我也试过没有@nonobjc标签的方法,结果一样。

IBDesigner 中是否存在阻止使用命名颜色的限制?

有人可以建议一种方法来解决 IBDesigner 中的崩溃问题吗?

你问过:

Can someone suggest a method to overcome this crash in IBDesigner?

我们无法解决命名颜色问题,但我们肯定可以通过避免强制展开运算符来消除崩溃,!。例如。您可以改用 nil-合并运算符 ??,这样您就有了一些 IB 的后备颜色,例如

backgroundColor = UIColor(named: "Color.Button.Background") ?? .blue

但是,如果你不强制解包,它就不会崩溃。虽然它不会在 IB 中使用您命名的颜色,但它会在您 运行 应用程序时使用。


就个人而言,我会避免在可设计视图本身中设置通常在 IB 中设置的任何属性(例如 backgroundColor)。我认为在 IB 中查看某些视图,更改 属性,例如背景颜色,但没有正确呈现它是非常令人困惑的。

可以在 IB 中配置的内容应该保留在 IB 中以避免混淆。


但是让我们考虑一个例子,我确实希望自定义颜色 属性 使用命名颜色。我会声明一个 @IBInspectable 颜色 属性,例如,考虑这个带有自定义 fillColor:

的圆形视图
@IBDesignable
class CircleView: UIView {
    let shapeLayer = CAShapeLayer()

    @IBInspectable var fillColor: UIColor = .blue { didSet { shapeLayer.fillColor = fillColor.cgColor } }

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configure()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        updatePaths()
    }
}

private extension CircleView {
    func configure() {
        layer.addSublayer(shapeLayer)
        shapeLayer.fillColor = fillColor.cgColor
    }

    func updatePaths() {
        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        let radius = min(bounds.width, bounds.height) / 2
        shapeLayer.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true).cgPath
    }
}

然后我会在 IB 属性检查器中设置命名颜色:


另一种方法是不在资产目录中使用命名颜色,而是定义您自己的 UIColor 扩展名:

extension UIColor {
    static let buttonBackground = #colorLiteral(red: 0, green: 1, blue: 1, alpha: 1)
}

然后当你想设置一些颜色时属性,你可以这样做:

backgroundColor = .buttonBackground

这种方法的缺点是您无法将 IB 中的命名颜色用于其他控件。但这是另一种需要考虑的模式。

好的,事实证明这是一个错误。已在 Xcode 11.4 中修复:

Fixed a bug where using named colors in IBInspectable properties would use a fixed color at runtime, instead of the dynamic color from the asset catalog. (55248109) (FB7248211)