我很少在UIView子类中重写drawRect,通常更喜欢layer.contents使用预渲染图像进行设置,并且经常采用多个子层或子视图并根据输入参数进行操作。IB是否有方法呈现这些更复杂的视图堆栈?
layer.contents
谢谢@zisoft为我提供的线索prepareForInterfaceBuilder。Interface Builder的渲染周期有一些细微差别,这些细微差别是我遇到问题的根源,并且值得注意…
prepareForInterfaceBuilder
-drawRect
在UIButton控件状态上设置图像有效。如果牢记一些注意事项,则任意层堆栈似乎都可以工作…
initWithFrame:
..not initWithCoder。 awakeFromNib也不会被调用。
initWithCoder
awakeFromNib
init...
即,每当您在文件中进行更改时,每次重新编译一次。更改IBInspectable属性时,不会再次调用init。然而…
这就像在所有IBInspectables以及其他内置属性上包含KVO一样。您可以通过_setup首先调用您的方法来测试您自己init..。更改IBInspectable无效。然后将呼叫也添加到 prepareForInterfaceBuilder。哇!注意,您的运行时代码可能将需要一些额外的KVO,因为它不会调用该prepareForIB方法。下面的更多内容…
_setup
init..
prepareForIB
至少对于我的UIButton子类,调用[self setImage:img forState:UIControlStateNormal]在IB中无效。您需要prepareForInterfaceBuilder通过KVO挂钩或通过KVO挂钩调用它。
UIButton
[self setImage:img forState:UIControlStateNormal]
进行无效更改时,有时会造成混乱。检查构建日志。
我一直挂在几个不同的支持流程上,他们把整个机器拖走了。 大量申请Force Quit。
Force Quit
(更新:自从XCode6退出beta版以来,这并不是真的。很少挂起了。)
更新
IBInspectable
下面是一个有效的IBDesignable UIButton子类的示例代码。 注意,prepareForInterfaceBuilder实际上并不是必需的,因为KVO会监听对我们相关属性的更改并触发重绘。更新:请参见上面的第8点。
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 *)aDecoder { self = [super initWithCoder:aDecoder]; 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