你问:
有人可以建议一种方法来克服 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 中将指定颜色用于其他控件。但这是另一种需要考虑的模式。