【问题标题】:IB Designables: Failed to render and update auto layout status ...The agent crashedIB Designables:无法渲染和更新自动布局状态...代理崩溃
【发布时间】:2020-06-29 00:27:58
【问题描述】:

当我在 IBDesignable 类中有以下代码时,界面构建器代理正在崩溃。

    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 中的这种崩溃问题吗?

【问题讨论】:

  • 和@objc没有区别
  • 设计师可以从资产目录中选择颜色,因为它们在设计师中任何对象的自定义颜色选择列表中都可用。一定和 UIColor init 有关。

标签: swift xcode interface-builder


【解决方案1】:

你问:

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

我们无法解决命名颜色问题,但我们当然可以通过避免强制展开运算符! 来消除崩溃。例如。您可以改用nil-coalescing 运算符??,这样您就可以为 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 中将指定颜色用于其他控件。但这是另一种需要考虑的模式。

【讨论】:

  • 谢谢罗伯。很清楚的解释。我正在使用颜色目录来处理暗模式。我已经覆盖了包含该对象所有实例的一致配置的类,因此 IB 中的表示概念不太重要。
【解决方案2】:

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

修复了在 IBInspectable 属性中使用命名颜色会在运行时使用固定颜色而不是资产目录中的动态颜色的错误。 (55248109) (FB7248211)

【讨论】:

    猜你喜欢
    • 2017-02-05
    • 1970-01-01
    • 2018-03-25
    • 2018-05-11
    • 1970-01-01
    • 2019-11-17
    • 2015-02-07
    • 1970-01-01
    相关资源
    最近更新 更多