当前位置: 首页 > 面试题库 >

接口构建器是否可以呈现不覆盖drawRect的IBDesignable视图:

柳绪
2023-03-14
问题内容

我很少在UIView子类中重写drawRect,通常更喜欢layer.contents使用预渲染图像进行设置,并且经常采用多个子层或子视图并根据输入参数进行操作。IB是否有方法呈现这些更复杂的视图堆栈?


问题答案:

谢谢@zisoft为我提供的线索prepareForInterfaceBuilder。Interface
Builder的渲染周期有一些细微差别,这些细微差别是我遇到问题的根源,并且值得注意…

  1. 确认:您不需要使用-drawRect

在UIButton控件状态上设置图像有效。如果牢记一些注意事项,则任意层堆栈似乎都可以工作…

  1. IB用途initWithFrame:

..not initWithCoderawakeFromNib也不会被调用。

  1. init... 每个会话仅被调用一次

即,每当您在文件中进行更改时,每次重新编译一次。更改IBInspectable属性时,不会再次调用init。然而…

  1. prepareForInterfaceBuilder 每次属性更改都被调用

这就像在所有IBInspectables以及其他内置属性上包含KVO一样。您可以通过_setup首先调用您的方法来测试您自己init..。更改IBInspectable无效。然后将呼叫也添加到
prepareForInterfaceBuilder。哇!注意,您的运行时代码可能将需要一些额外的KVO,因为它不会调用该prepareForIB方法。下面的更多内容…

  1. init... 现在绘制,设置图层内容等还为时过早。

至少对于我的UIButton子类,调用[self setImage:img forState:UIControlStateNormal]在IB中无效。您需要prepareForInterfaceBuilder通过KVO挂钩或通过KVO挂钩调用它。

  1. 当IB无法渲染时,它不会使您的组件空白,而是保留最后一个成功的版本。

进行无效更改时,有时会造成混乱。检查构建日志。

  1. 提示:将活动监视器放在附近

我一直挂在几个不同的支持流程上,他们把整个机器拖走了。 大量申请Force Quit

(更新:自从XCode6退出beta版以来,这并不是真的。很少挂起了。)

更新

  1. 6.3.1在IB版本中似乎不喜欢KVO。现在,您似乎需要标记来捕获Interface Builder而不是设置KVO。可以,因为该prepareForInterfaceBuilder方法有效地KVO了所有IBInspectable属性。不幸的是,此行为未在运行时以某种方式反映出来,因此需要手动KVO。请参阅下面的更新的示例代码。

UIButton子类示例

下面是一个有效的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


 类似资料:
  • 问题内容: 你能 声明这样 的函数吗? 然后像这样 重新声明 它… 这样可以覆盖函数吗? 可以吗 问题答案: 编辑 解决此答案未直接解决原始问题的评论。如果您是通过Google搜索到达的,请从此处开始 有一个名为override_function的函数可以实际使用。但是,由于此函数是Advanced PHP Debugger扩展的一部分,因此很难为生产使用提供参数。因此,我要说“否”,不可能以原始

  • 问题内容: 我正在使用Sphinx的autodoc插件来自动记录一组模块。我有一个函数accepts ,我想重写文档以显示Python stdlib文档使用的稍微更好的样式。 是否可以覆盖特定功能的自动文档输出? 问题答案: 可以使用以下方法覆盖签名: 但是,具有覆盖签名的函数不会与通过引入的其他函数进行排序。对每个函数使用显式指令可以解决此问题: 加成 您还可以附加到文档字符串: 要覆盖签名和文

  • 或者特别是:两者之间的区别是什么 和 它会以任何方式影响实现类吗?

  • 我目前正在试图弄清楚分解为swing(1.5)和JavaFX(1.0.1)对JavaFX部分的影响。就我(关于这个主题的知识非常有限)而言,我理解使用来绘制其原始swing组件(?)将其添加到JavaFX节点中。 现在我的问题是,对象是否仍然可以与?我指的是工具提示和滚动以及普通提供的类似东西。由于我的知识和时间有限,我想知道是否值得深入研究JFRE-FX(这些图表是否仍然可以与之交互),或者这些

  • 问题内容: 我所知道的是,编译器在字节码中编写了一个默认的无参数构造函数。但是,如果我们自己编写,则该构造函数会自动调用。这种现象是构造函数压倒一切的吗? 问题答案: 您所描述的不是最重要的。如果您未指定默认构造函数,则编译器将创建一个默认构造函数。如果是子类,它将调用默认的父构造函数(super()),还将所有实例变量初始化为由该类型的默认值确定的默认值(数字类型为0,布尔值为false,对象为

  • 问题内容: 在Java中是否可以覆盖Objects数组的toString? 例如,假设我创建了一个简单的类(由于这是一个普遍的问题,所以实际上是哪个类并不重要)。客户端一旦创建了一个数组并使用了它,是否有可能不打印该数组的地址,而是打印一个定制的? PS:当然,我不能只在类中重写它,因为它与单个实例有关。 问题答案: 不会。您当然可以创建一个静态方法User.toString(User []),但