UIButton with IB_DESIGNABLE throws runtime attribute warning and does not render in Interface Builder UIButton with IB_DESIGNABLE throws runtime attribute warning and does not render in Interface Builder objective-c objective-c

UIButton with IB_DESIGNABLE throws runtime attribute warning and does not render in Interface Builder


I have been working extensively with Live Views since it's introductions and like a lot of new features in Xcode initially, it has some flaws. Still I like it a lot and I hope that it will be improved in newer versions.

Cause:

Live Views work with @property properties that get a special IB_Designable tag that will give the UI class extra attributes it can approach via User Defined Runtime Attributes that will be set through the Attributes Inspector. You will see that all those properties also exist in the Identity Inspector. The root cause of the problem is that it cannot map those User Defined Runtime Attributes anymore to exposed properties.

As soon as you open up a Storyboard or xib that uses IB_Designable, Xcode will recompile the screen at every change if you have "Automatically Refresh Views" turned on. Since your code influences your UI as well this doesn't have to be a change in Interface Builder per se.

With simpler projects on faster machines this works pretty well the majority of the time. With larger projects that also have more IB_Designable the CPU simply doesn't have enough capacity to keep up with you and you will get a sort of time-out error while rendering the UI. This is the cause of the "warning: IB Designables: Ignoring user defined runtime attribute for key path "spacingBetweenLabelAndImage" on instance of "UIButton". Hit an exception when attempting to set its value: [ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key spacingBetweenLabelAndImage." error.

It will also not update your UI anymore with your custom code. This is not a problem when you run it though, because at run time it will reflect those changes.

Another cause can be that your code simply doesn't compile when it tries to compile in the background. This is inevitable when you are working on code so that triggers it frequently as well.

Solution:

We need to make sure that your custom view class compiles again so the properties can be set successfully via Interface Builder

  • While in a storyboard, go to "Editor" in the top bar menu
  • deselect "Automatically refresh views" if it was still turned on
  • Close all your storyboard tabs
  • Rebuild the project
  • Fix all build errors if any
  • Re-open your storyboard.
  • Go to "Editor" again and click "Refresh All Views"

The warnings should be gone and if it worked before you will see your custom view code again as well.

After a comment below by sunkas: it's always a very good idea to clean your solution thoroughly in case of any weird problems that persist.


How I personally fixed this:

In the identity inspector in User Defined Runtime Attributes I noticed that I had an old IB_Inspectable element that I had deleted from my code, but it was still in there. Removing it with the - button got rid of this error.

identityinspector


Try changing your "CGFloat" declaration for spacingBetweenLabelAndImage into "NSNumber".

As far as I know, you can't call "setValue:" on a C-type variable.

Changing the declaration of "spacingBetwenLabelAndImage" to NSNumber would also require you to change a bit of code too:

CGFloat halfSpacing = self.spacingBetweenLabelAndImage == 0 ? 0 : self.spacingBetweenLabelAndImage / 2;

might become something like:

CGFloat halfSpacing = (self.spacingBetweenLabelAndImage ? ([self.spacingBetweenLabelAndImage floatValue] / 2) : 0.0);

(I'm not 100% certain if this is a perfect translation of the first line, but I wanted to show how to get a floatValue out of a NSNumber)