谢谢@zisoft为我提供的线索
prepareForInterfaceBuilder。Interface
Builder的渲染周期有一些细微差别,这些细微差别是我遇到问题的根源,并且值得注意…
- 确认:您不需要使用
-drawRect
。
在UIButton控件状态上设置图像有效。如果牢记一些注意事项,则任意层堆栈似乎都可以工作…
- IB用途
initWithframe:
..not
initWithCoder。
awakeFromNib也不会被调用。
init...
每个会话仅被调用一次
即,每当您在文件中进行更改时,每次重新编译一次。更改IBInspectable属性时,不会再次调用init。然而…
prepareForInterfaceBuilder
每次属性更改都被调用
这就像在所有IBInspectables以及其他内置属性上包含KVO一样。您可以通过
_setup首先调用您的方法来测试您自己
init..。更改IBInspectable无效。然后将呼叫也添加到
prepareForInterfaceBuilder。哇!注意,您的运行时代码可能将需要一些额外的KVO,因为它不会调用该
prepareForIB方法。下面的更多内容…
init...
现在绘制,设置图层内容等还为时过早。
至少对于我的
UIButton子类,调用
[self setImage:imgforState:UIControlStateNormal]在IB中无效。您需要
prepareForInterfaceBuilder通过KVO挂钩或通过KVO挂钩调用它。
- 当IB无法渲染时,它不会使您的组件空白,而是保留最后一个成功的版本。
进行无效更改时,有时会造成混乱。检查构建日志。
提示:将活动监视器放在附近
我一直挂在几个不同的支持流程上,他们把整个机器拖走了。 大量申请Force Quit
。
(更新:自从XCode6退出beta版以来,这并不是真的。很少挂起了。)
更新
- 6.3.1在IB版本中似乎不喜欢KVO。现在,您似乎需要标记来捕获Interface Builder而不是设置KVO。可以,因为该
prepareForInterfaceBuilder
方法有效地KVO了所有IBInspectable
属性。不幸的是,此行为未在运行时以某种方式反映出来,因此需要手动KVO。请参阅下面的更新的示例代码。
UIButton子类示例
下面是一个有效的IBDesignable
UIButton子类的示例代码。
注意,
prepareForInterfaceBuilder实际上并不是必需的,因为KVO会监听对我们相关属性的更改并触发重绘。
IB_DESIGNABLE@interface SBR_InstrumentLeftHUDBigButton : UIButton@property (nonatomic, strong) IBInspectable NSString *topText;@property (nonatomic) IBInspectable CGFloat topTextSize;@property (nonatomic, strong) IBInspectable NSString *bottomText;@property (nonatomic) IBInspectable CGFloat bottomTextSize;@property (nonatomic, strong) IBInspectable UIColor *borderColor;@property (nonatomic, strong) IBInspectable UIColor *textColor;@end@implementation HUDBigButton{ BOOL _isInterfaceBuilder;}- (id)initWithCoder:(NSCoder *)aDeprer{ self = [super initWithCoder:aDeprer]; if (self) { [self _setup]; } return self;}//---------------------------------------------------------------------- (id)initWithframe:(CGRect)frame{ self = [super initWithframe:frame]; if (self) { [self _setup]; } return self;}//---------------------------------------------------------------------- (void)_setup{ // Defaults. _topTextSize = 11.5; _bottomTextSize = 18; _borderColor = UIColor.whiteColor; _textColor = UIColor.whiteColor;}//---------------------------------------------------------------------- (void)prepareForInterfaceBuilder{ [super prepareForInterfaceBuilder]; _isInterfaceBuilder = YES; [self _render];}//---------------------------------------------------------------------- (void)awakeFromNib{ [super awakeFromNib]; if (!_isInterfaceBuilder) { // shouldn't be required but jic... // KVO to update the visuals @weakify(self); [self bk_addObserverForKeyPaths:@[@"topText", @"topTextSize", @"bottomText", @"bottomTextSize", @"borderColor", @"textColor"] task:^(id obj, NSDictionary *keyPath) { @strongify(self); [self _render]; }]; }}//---------------------------------------------------------------------- (void)dealloc{ if (!_isInterfaceBuilder) { [self bk_removeAllBlockObservers]; }}//---------------------------------------------------------------------- (void)_render{ UIImage *img = [SBR_Drawing imageOfHUDButtonWithframe:self.bounds edgeColor:_borderColor buttonTextColor:_textColor topText:_topText topTextSize:_topTextSize bottomText:_bottomText bottomTextSize:_bottomTextSize]; [self setImage:img forState:UIControlStateNormal];}@end


