带有 IB_DESIGNABLE 的 UIButton 会引发运行时属性警告,并且不会在 Interface Builder 中呈现

UIButton with IB_DESIGNABLE throws runtime attribute warning and does not render in Interface Builder(带有 IB_DESIGNABLE 的 UIButton 会引发运行时属性警告,并且不会在 Interface Builder 中呈现)

本文介绍了带有 IB_DESIGNABLE 的 UIButton 会引发运行时属性警告,并且不会在 Interface Builder 中呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行 Xcode 6.1,并且我已经在很多项目中使用 IB_DESIGNABLE 和 IBInspectable,但突然之间它就不再工作了.我创建了子类按钮,将图像和标题垂直居中排列,并允许用户通过 IB 和 IBInspectable 设置边框宽度和颜色.

I'm running Xcode 6.1 and I have been using IB_DESIGNABLE with IBInspectable for quite a few projects already but all of the sudden it just doesn't work anymore. I have created subclassed buttons that arrange the image and the title vertically centred above each other and enable the user to set a border width and color through IB with IBInspectable.

记录了以下警告,并且在 drawRect 中没有可用的代码预览:

The following warning is logged and there is no preview available of my code in drawRect:

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: [<UIButton 0x7f9278591260> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key spacingBetweenLabelAndImage.

不过,它呈现的运行时就像我打算呈现的那样,它还尊重我通过 IB 添加的相同自定义间距.

Still, runtime it renders like I intended it to render and it also honours that same custom spacing I've added through IB.

这是重新排列按钮和标题的菜单按钮的代码:

Here's the code of the menubutton that rearranges the button and the title:

#import "HamburgerButton.h"

IB_DESIGNABLE
@interface HamburgerImageButton : HamburgerButton

@property IBInspectable CGFloat spacingBetweenLabelAndImage;

@end

实施:

#import "HamburgerImageButton.h"

@implementation HamburgerImageButton

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    CGSize imageSize = self.imageView.frame.size;
    CGSize titleSize = self.titleLabel.frame.size;

    // Move the label left and the image right by half the width
    CGFloat leftInset = titleSize.width / 2;
    CGFloat rightInset = imageSize.width / 2;

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

    CGFloat topInset = imageSize.height / 2 + halfSpacing;
    CGFloat bottomInset = titleSize.height / 2 + halfSpacing;

    UIEdgeInsets imageInsets = UIEdgeInsetsMake(-bottomInset, leftInset, bottomInset, -leftInset);
    UIEdgeInsets titleInsets = UIEdgeInsetsMake(topInset, -rightInset, -topInset, rightInset);
    self.imageEdgeInsets = imageInsets;
    self.titleEdgeInsets = titleInsets;
}

@end

您可能已经注意到它继承了 HamburgerButton.这个基本的汉堡按钮没有图像,它只在按钮周围绘制边框.这个基本的汉堡按钮有完全相同的问题:它没有在 IB 的 drawRect 中绘制它的边框并且它有相同类型的错误.为了完整起见,这是该代码:

You've probably noticed it inherits HamburgerButton. This basic hamburger button does not have an image and it only draws the border around the button. This basic hamburger button has exactly the same problem: it does not draw it's border in drawRect in IB and it has the same type of errors. Here's that code for sake of completeness:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface HamburgerButton : UIButton

@property IBInspectable CGFloat borderWidth;
@property IBInspectable UIColor *borderColor;

@end

实施:

#import "HamburgerButton.h"
#import <QuartzCore/QuartzCore.h>

@implementation HamburgerButton

- (void)copyInspectables {
    self.layer.borderWidth = self.borderWidth;
    self.layer.borderColor = self.borderColor.CGColor;
}

- (void)drawRect:(CGRect)rect {
    [self copyInspectables];
}

@end

我真的不明白为什么它只是发出警告而没有别的.我并没有真正改变我所做的.我检查了故事板,它是 iOS 7 及更高版本,旨在在 Xcode 6(最新)中运行.

I don't really understand why it just throws a warning and nothing else. I didn't really change what I did. I've checked the storyboard, it's iOS 7 and up, meant to run in Xcode 6 (latest).

它抱怨无法在 UIButton 上找到该值,这有点奇怪,因为我已经对它进行了子类化.

It complains about not being able to find that value on UIButton and that's a bit weird because I've subclassed it.

更新:所以我改变了周围的一切,它奏效了.现在它再次出现,没有改变任何其他东西.我认为 Xcode 6.1 中存在错误...:/

Update: So I changed everything around and it worked. Now it craps out again, without changing anything else. I think there's a bug in Xcode 6.1... :/

推荐答案

自从 Live Views 推出以来,我一直在广泛使用它,并且与 Xcode 中的许多新功能一样,它有一些缺陷.我还是很喜欢它,我希望它会在新版本中得到改进.

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.

实时视图与@property 属性一起使用,这些属性获得一个特殊的 IB_Designable 标记,该标记将为 UI 类提供额外的属性,它可以通过用户定义的运行时属性访问,这些属性将通过属性检查器设置.您将看到所有这些属性也存在于 Identity Inspector 中.问题的根本原因是它无法再将那些用户定义的运行时属性映射到公开的属性.

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.

一旦您打开使用 IB_Designable 的 Storyboard 或 xib,如果您打开了自动刷新视图",Xcode 将在每次更改时重新编译屏幕.由于您的代码也会影响您的 UI,因此不必更改 Interface Builder 本身.

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.

在更快的机器上进行更简单的项目,这在大多数情况下都能很好地工作.对于具有更多 IB_Designable 的大型项目,CPU 根本没有足够的能力跟上您的速度,并且您在渲染 UI 时会遇到一种超时错误.这是 警告的原因:IB Designables:忽略UIButton"实例上键路径spacingBetweenLabelAndImage"的用户定义运行时属性.尝试设置其值时遇到异常:[setValue:forUndefinedKey:]:此类与键间距BetweenLabelAndImage 的键值编码不兼容." 错误.

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.

它也不会再使用您的自定义代码更新您的 UI.但是,当您运行它时,这不是问题,因为在运行时它会反映这些更改.

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.

我们需要确保您的自定义视图类再次编译,以便可以通过 Interface Builder 成功设置属性

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

  • 在故事板中,转到顶部栏菜单中的编辑器"
  • 如果自动刷新视图"仍处于开启状态,请取消选择它
  • 关闭所有故事板标签
  • 重建项目
  • 修复所有构建错误(如果有)
  • 重新打开您的故事板.
  • 再次进入编辑器",点击刷新所有视图"

警告应该消失,如果它在您再次看到您的自定义视图代码之前有效.

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

在 sunkas 发表评论后:clean 总是一个好主意 彻底解决您的解决方案,以防出现任何持续存在的奇怪问题.

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.

这篇关于带有 IB_DESIGNABLE 的 UIButton 会引发运行时属性警告,并且不会在 Interface Builder 中呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:带有 IB_DESIGNABLE 的 UIButton 会引发运行时属性警告,并且不会在 Interface Builder 中呈现

基础教程推荐