Xcode 9: Using named colors with IBDesignable and IBInspectable results in Interface Builder error, but compiles without issue
Asked Answered
P

2

12

I use UIColor.named("myColor") throughout my app since Xcode 9 came out. While having a shot at a custom implementation of UITextField as an IBDesignable class, I kept getting the following error:

error: IB Designables: Failed to render and update auto layout status for ViewController (): The agent crashed

Furthermore, my class has several IBInspectable properties, including of type UIColor, but in the Interface Builder dropdown for these properties I could only select the standard colors, my named colors would not show up as they do for standard class properties.

With that latter issue as a clue for the first one, the unsatisfactory and temporary solution has been to not use named colors in my IBDesignable class. Or alternatively, not use IBDesignable.

This is probably a bug, but I'm wondering if other people out there have experienced this issue, and if there are any fixes they've come up with.

Pope answered 1/11, 2017 at 8:36 Comment(5)
What about having a String IBInspectable property such as colourName which you then use to set your custom colours?Stertorous
I just ran into this problem. Named colors don't show up in the dropdown when I try to select a color on an IBInspectable property in InterfaceBuilder.Nunciature
@Hodson, I just tried your suggestion, and it works, but I don't think it's a satisfactory solution. I'm using magic strings with the chance of typos and refactoring issues.Nunciature
Just to add. Setting custom named colours as IBInspectables doesn't work in the Storyboard, as noted in the comments above, but the values are respected at run-time. If you are overriding something that has a separate Storyboard property, e.g. Background Colour, make sure that is set to default. For me, a workaround was to add a IBInspectable property called useDesignColours in which I have code to set the required properties with named colours. If I set that to true in the storyboard, the colours appear at run time (not build time though!)Tardif
Also, If I select a colour via the previous colour choices, which is actually one of the named colour shades, in the storyboard for an IBInspectable it does give it the right name in the storyboard BUT in brackets it says (missing), e.g. "sp Dark Purple (missing)"Tardif
B
8

[As of Xcode 9.2] This is an unfortunate workaround, but for now I'm using IB-specific stand-in colors. It's not perfect, but we can at least see something while designing in Interface Builder.

@IBDesignable
class MyView: UIView {

    @IBInspectable
    var addCoolSubview: Bool = false {
        didSet {
            if self.addCoolSubview {
                let coolView = CoolView() // Some custom view with a `coolColor` property.

                #if TARGET_INTERFACE_BUILDER
                coolView.coolColor = UIColor.blue // An IB-only stand-in color.
                #else
                coolView.coolColor = UIColor(named: "myCoolBlue") // The run-time color we really want.
                #endif

                self.addSubview(coolView)
            }
        }
    }

}

Every UIView also has a prepareForInterfaceBuilder() method, which runs only when building for Interface Builder, that could be overridden to similar effect.

@IBDesignable
class MyOtherView: UIView {

    var myWarmColor: UIColor? = UIColor(named: "myWarmColor") // Will be `nil` in IB.

    // ... view does something with `myWarmColor` that would be visible in IB ...

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        // Set some IB-only stand-in colors here:
        self.myWarmColor = UIColor.orange
    }

}

With regard to choosing named colors in @IBInspectable properties in Interface Builder, it's only half-broken. As a workaround, you can choose a named color from the Recently Used Colors section, if you can pick it out of the group by sight. When you pick a named color, it will properly display the name, but append (missing) for whatever reason. Just ignore the (missing); it will display properly in IB and at run-time.

One other point of note is that Xcode (as of 9.2) might try to add the named color again to your Storyboard file, so you'll have to check the XML to see if the color is defined there multiple times (color definitions are near the bottom). Or you could just roll with, and eventually Xcode will notice and fix it by itself, blaming the duplicate color definition on SCM.

Bromidic answered 27/2, 2018 at 19:31 Comment(0)
R
0

You just have to specify the bundle.

UIColor(named: "myColor", in: Bundle(for: AppDelegate.self), compatibleWith: nil)!

I found it in another question and works for me on XCode 14.2.

Reseta answered 5/2, 2023 at 22:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.