@Ibdesignable Error: Ib Designables: Failed to Update Auto Layout Status: Interface Builder Cocoa Touch Tool Crashed

@IBDesignable error: IB Designables: Failed to update auto layout status: Interface Builder Cocoa Touch Tool crashed

There are crash reports generated when Interface Builder Cocoa Touch Tool crashes. Theses are located in ~/Library/Logs/DiagnosticReports and named IBDesignablesAgentCocoaTouch_*.crash. In my case they contained a useful stack-trace that identified the issue in my code.

IB Designables for storyboard UITableViewCell: Failed to render and update auto layout status for CountdownViewController The agent crashed

This is happening because your dummyView is an IBOutlet and is implicitly unwrapped. prepareForInterfaceBuilder will be called before dummyView is initialized. You can prevent a crash by changing your code to dummyView?.backgroundColor = .red but then nothing will be rendered because dummyView == nil.

It doesn't make a ton of sense to mix IBDesignable with IBOutlet. In general, IBDesignable is meant to make run time layout and drawing visible at design time. But IBOutlets are necessarily already visible at design time. This might however be desirable in a xib. For a discussion of that see here and here.

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

You asked:

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

We can’t solve the named color problem, but we certainly can eliminate the crash by avoiding forced unwrapping operator, !. E.g. you could use a nil-coalescing operator, ??, instead, so you have some fall-back color for IB, e.g.

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

But, if you don’t force unwrap, it won’t crash. And while it won’t use your named color in IB, it will when you run the app.


Personally, I’d avoid setting any properties usually set in IB (such as backgroundColor) in a designable view, itself. I think it’s exceedingly confusing to be looking at some view in IB, change a property, such as the background color, and not have it render correctly.

What can be configured in IB should probably be left in IB to avoid any confusion.


But let’s consider an example where I did want a custom color property to use a named color. I’d declare an @IBInspectable color property, e.g., consider this circle view with a custom 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
}
}

I’d then set the named color in IB attributes inspector:

Sample Image


The other approach, is to not use named colors in the asset catalog, but rather define your own UIColor extension:

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

Then when you want to set some color property, you can do something like:

backgroundColor = .buttonBackground

The downside of this approach is that you lose the ability to use the named color within IB for other controls. But it’s another pattern to consider.



Related Topics



Leave a reply



Submit