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

时间:2014-10-30 14:59:15

标签: ios objective-c uibutton interface-builder xcode6

我正在运行Xcode 6.1并且我已经将IB_DESIGNABLE与IBInspectable一起用于了不少项目,但突然间它再也没有用了。我创建了子类按钮,将图像和标题垂直居中放置,使用户可以通过IB使用IBInspectable设置边框宽度和颜色。

记录以下警告,并且我的代码无法预览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添加的相同自定义间距。

这里是重新排列按钮和标题的menubutton的代码:

#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中绘制它的边界,它有相同类型的错误。为了完整起见,这里是代码:

#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(最新版本)中运行。

它抱怨无法在UIButton上找到这个价值而且这有点奇怪,因为我已将其分类。


更新: 所以我改变了一切,它起作用了。现在它再次扯掉,没有改变任何其他东西。我认为Xcode 6.1中存在一个错误......:/

7 个答案:

答案 0 :(得分:67)

我一直在与Live Views进行广泛的合作,因为它的介绍和最初的Xcode中的许多新功能一样,它有一些缺陷。我仍然喜欢它,我希望它能在新版本中得到改进。

的原因:

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

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

在更快的机器上使用更简单的项目,这在大多数情况下都能很好地工作。对于同样拥有更多IB_Designable的大型项目,CPU根本没有足够的容量来跟上你,并且在渲染UI时会出现一种超时错误。这是&#34;警告的原因:IB Designables:忽略用户定义的关键路径的运行时属性&#34; spacingBetweenLabelAndImage&#34;在&#34; UIButton&#34;的实例上。尝试设置其值时遇到异常:[setValue:forUndefinedKey:]:此类不是键值spacerBetelLelelAndImage的键值编码兼容。&#34; 错误。

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

另一个原因可能是您的代码在尝试在后台编译时根本无法编译。当您处理代码时,这是不可避免的,因此也会频繁触发它。

解决方案:

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

  • 在故事板中,转到&#34;编辑器&#34;在顶部栏菜单
  • 取消选择&#34;自动刷新视图&#34;如果它仍然打开
  • 关闭所有故事板标签
  • 重建项目
  • 修复所有构建错误(如果有)
  • 重新打开故事板。
  • 转到&#34;编辑&#34;再次单击&#34;刷新所有视图&#34;

警告应该消失,如果有效,你也会再次看到自定义视图代码。

在sunkas发表评论之后:如果任何奇怪的问题仍然存在,那么clean你的解决方案总是一个非常好的主意。

答案 1 :(得分:23)

我个人如何解决这个问题:

在用户定义的运行时属性中的身份检查器中,我注意到我有一个旧的IB_Inspectable元素,我从代码中删除了它,但它仍在那里。使用 - 按钮删除它可以消除此错误。

identityinspector

答案 2 :(得分:5)

尝试将CGFloat的“spacingBetweenLabelAndImage”声明更改为“NSNumber”。

据我所知,you can't call "setValue:" on a C-type variable

将“spacingBetwenLabelAndImage”的声明更改为NSNumber也需要您更改一些代码:

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

可能会变成:

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

(如果这是第一行的完美翻译,我不是100%肯定,但我想展示如何从NSNumber中获取floatValue)

答案 3 :(得分:1)

我使用了Departamento B提供的方法,但它并没有真正起作用。但是,我解决了我的问题 1.从故事板中选择有缺陷的视图 2.单击(编辑器 - 调试选定视图) 希望这有帮助

答案 4 :(得分:1)

我遇到了类似的问题,但实际上我从类中删除了该属性,Interface Builder仍然抱怨缺少属性,很难。

尝试了许多事情,比如清洁,重建......但没有任何效果!

真正解决的是右键单击Storyboard文件,选择“打开为”,然后选择“源代码”。这打开了编辑器中的故事板XML内容,我找到了对缺失属性的引用,直到找到该部分:

<userDefinedRuntimeAttributes>
    <userDefinedRuntimeAttribute... keyPath="My Missing Property Name">
    ...
</userDefinedRuntimeAttributes>

删除整个部分后,我保存了文件并刷新了Interface Builder中的视图。现在所有的警告都消失了!

答案 5 :(得分:0)

如果您确定自己设置了所有设置器,并且在项目中导入了其他一些SDK并且遇到此问题, 检查Target中的'Linked Frameworks and Libraries'。一般。

在我正确链接了一些SDK框架之后,错误就消失了。

答案 6 :(得分:0)

我有这个错误,有两个目标时。一个是我的主要项目,另一个是目标,我持有可设计的类(为了更快的构建) 问题是在故事板中缺少一个模块。

enter image description here