如何在Objective-C中为IBInspectable设置默认值?

68

我知道在Swift中,IBInspectable属性的默认值可以设置为:

@IBInspectable var propertyName: propertyType = defaultValue。但是,在Objective-C中我该如何实现类似的效果,以便我可以在Interface Builder中将某些属性的默认值设置为某些值?


你有解决这个问题的办法吗? - Fogmeister
1
@Fogmeister 不好意思,不行。我开始觉得这是不可能的,因为 IB Inspectables 是与 Swift 同时推出的新功能,而 Swift 支持默认值。由于 ObjC 不支持默认值,而且极不可能苹果添加这样的功能到 ObjC,我非常怀疑这是可能的。他们可以添加一个 Xcode 宏(例如 IBDefaultValue),但这将支持传统语言,我认为苹果会反对。 - Can Poyrazoğlu
1
好的,谢谢你的答复 :D 那我就回到老方法吧。真烦人,你甚至不能把 UIFont 作为 IBInspectable 类型。我本以为可能会有这种可能性,因为 UILabel 有它。嘿,没关系 :) - Fogmeister
2
@Fogmeister 是的,这真的很烦人,但是我认为随着时间的推移,它会支持更多类型(看向你,枚举!)和功能。如果您想添加“字体”属性,请查看此链接:https://github.com/can16358p/CPTutorial/blob/master/CPTutorialBalloon.m (转到第212行)。这是一个我编写的小库,在Interface Builder中接受字体名称,并可以在IB和运行时动态解析字体名称字符串以获取实际字体。如果有帮助,请随意将其复制到您的项目中。 - Can Poyrazoğlu
好的,谢谢!我现在会去看一下。 - Fogmeister
之前报告了一个错误:http://www.openradar.me/19044397 并且被标记为可重现/重复... 但是重复主人似乎不在OpenRadar上。 - jscs
5个回答

63

IBInspectable 值在 initWithCoder: 之后且在 awakeFromNib: 之前设置,因此您可以在 initWithCoder: 方法中设置默认值。

@interface MyView : UIView
@property (copy, nonatomic) IBInspectable NSString *myProp;
@property (assign, nonatomic) BOOL createdFromIB;
@end

@implementation MyView

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if(self != nil) {
        self.myProp = @"foo";
        self.createdFromIB = YES;
    }
    return self;
}

- (void)awakeFromNib {
    if (self.createdFromIB) {
        //add anything required in IB-define way
    }
    NSLog(@"%@", self.myProp);
}

@end

12
谢谢,但我实际上正在寻找一种让这些价值被IB看到的方法。这有可能吗? - Can Poyrazoğlu
抱歉,我不知道。 - rintaro
3
@rintaro,你刚刚救了我的一命。我试图在initWithCoder:期间使用IBInspectables中的值来设置我的自定义控件,但是无法弄清为什么它们都为空。现在,我在awakeFromNib中设置了我的自定义控件,一切都好了。谢谢! - user2320861
3
谢谢您的答复!为了在storyboard中看到使用示例,您需要实现- (void)prepareForInterfaceBuilder方法,该方法将使用可检查的值来渲染内容。 - ElyashivLavi

1
我将我的代码写成这样。对我来说非常有效,无论是在界面构建器中设计还是作为应用程序运行。
@interface MyView : UIView

@property (copy, nonatomic) IBInspectable propertyType *propertyName;

@end

- (void)makeDefaultValues {
    _propertyName = defaultValue;
    //Other properties...
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self makeDefaultValues];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self makeDefaultValues];
    }
    return self;
}

这是否允许我检查Interface Builder中的值,这正是我所问的。 - Can Poyrazoğlu
你只能在属性检查器中看到“默认值”,但是你可以看到用代码编写的默认值绘制的视图。 - GetToSet
1
是的,谢谢你的回答,但我已经知道了。我正在寻找一种解决方案,使检查器能够获取这些默认值,就像在Swift中一样。 - Can Poyrazoğlu
也许我无法解决这个问题,但我认为在检查器中查看值并不必要,因为它已经绘制在视图上了。 - GetToSet
从编程角度来看,我不需要它们中的任何一个。但是在设计时(特别是将其交给非技术人员调整值时),这会成为一个问题。 - Can Poyrazoğlu

1
我这样使用
@IBInspectable var propertyNameValue:propertyType?
var propertyName:propertyType { return propertyNameValue ?? defaultValue }

如果propertyNameValuenil,则propertyName将返回defaultValue

1
它可能在Swift中运行,但问题出在Objective-C上。我们已经为Swift找到了解决方案。 - Can Poyrazoğlu
1
没关系,我们都会犯错 :) - Can Poyrazoğlu

-1

首先我尝试了重写getter方法,并做了如下操作:

- (UIColor *)borderColor {
    return _borderColor ?: [UIColor greenColor];
}

但是在那种情况下,我收到了有关未声明标识符_borderColor的问题。

好的,我尝试通过自定义getter来避免这个问题。

- (UIColor *)getBorderColor {
    return _borderColor ?: [UIColor greenColor];
}

实际上这不是一个合适的getter,因为我们没有将这个方法指定为getter。如果我们指定了,我们会收到未声明标识符的问题,这就是为什么我们不会这样做的原因。

然后我们在updateUI方法中使用这个方法来获取属性值。

此外,我们还必须重写setter:

- (void)setBorderColor:(UIColor *)borderColor {
  _borderColor = borderColor;
  [self updateUI];
}

这与接口生成器有何关系? - Shebuka
2
你需要添加 @synthesize borderColor=_borderColor,因为如果你提供了getter和setter,编译器就不会生成iVar。 - Adam Kaplan

-1

2
这是否允许我在IB检查器中看到默认值,这正是我所问的?否则,我知道宏和prepareForInterfaceBuilder方法。 - Can Poyrazoğlu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接