从 nib 加载的 UIButton 的子类未正确初始化

Posted

技术标签:

【中文标题】从 nib 加载的 UIButton 的子类未正确初始化【英文标题】:Subclasses of UIButton loaded from nibs are not initialized properly 【发布时间】:2010-09-03 17:20:07 【问题描述】:

我有一个非常简单的 UIButton 子类:

@interface MyButton : UIButton
@end

@implementation MyButton

- (id) initWithCoder:(NSCoder *)decoder

    if (!(self = [super initWithCoder:decoder]))
        return nil;

    NSLog(@"-[%@ initWithCoder:%@]", self, decoder);

    return self;


@end

在 Interface Builder 中,我添加了一个 UIButton,将其按钮类型设置为 Rounded Rect,并将其类标识设置为 MyButton

运行时,我有以下日志:

-[<MyButton: 0x5b23970; baseClass = UIButton; frame = (103 242; 114 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x5b23a90>> initWithCoder:<UINibDecoder: 0x6819200>]

但按钮不再是圆形矩形按钮了。

ios 3.2 和 iOS 4 上均观察到。

这是一个错误还是我遗漏了一些明显的东西?

以编程方式创建 MyButton 的实例不是可接受的答案,谢谢。

【问题讨论】:

【参考方案1】:

以编程方式,您使用+[UIButton buttonWithType:] 实例化一个按钮,它实际上是一个返回UIButton 子类的工厂。因此,如果您从 UIButton 派生,您实际上不是从圆形矩形按钮类 (UIRoundedRectButton) 派生,而是从通用按钮类派生。但是你不能继承UIRoundedRectButtonAFAIK,因为它是一个内部类。

从 UIButton 派生似乎有问题,我看到很多人建议从 UIControl 派生而不是自己实现绘图。

但您可能会发现这些文章很有帮助:

How to override -drawrect in UIButton subclass?

http://www.cocoabuilder.com/archive/cocoa/284622-how-to-subclass-uibutton.html

http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/

另外,我不知道您为什么要从 UIButton 派生,但如果您想做一些不涉及覆盖任何其他方法的自定义,那么使用您可以执行以下操作的事实可能会有所帮助:

- (id)initWithCoder:(NSCoder *)decoder 
   // Decode the frame
   CGRect decodedFrame = ...;
   [self release];
   self = [UIButton buttonWithType:UIButtonTypeRoundedRect];
   [self setFrame:decodedFrame];
   // Do the custom setup to the button
   return self;

【讨论】:

上面的代码看起来很有希望,但我不能让它工作。我以为我可以用它来对 IBOutlet UIButton 执行自定义,但是唉。我很想知道支持这个答案的两个人是如何实现它的。 我无法推断我们应该做什么来解码帧。有什么提示吗? @jemmons:你可以使用NSStringFromCGRectCGRectFromString @DarkDust 谢谢!虽然这不是神秘的部分。我从哪里得到我 CGRectFromString 我的 rect 的字符串? decoder 没有“框架”、“矩形”、“边界”甚至“大小”或“中心”的任何键。那么你到底做了什么来解码帧? 要么自己编码和解码,要么尝试调用[super initWithCoder:][super encodeWithCoder:]。如果您仍有问题,请提出新问题,而不是在 cmets 中讨论。【参考方案2】:

我不确定这是否能满足您的需求,但在这些情况下,我倾向于覆盖 -awakeFromNib 而不是 -initWithCoder:。这样做能解决您遇到的问题吗?

【讨论】:

+1 我不明白你为什么在这里被否决,这是一个有效的答案。

以上是关于从 nib 加载的 UIButton 的子类未正确初始化的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的 Nib 正确加载我自定义的 UIScrollView 子类?

为 UIView 子类加载 Nib 的正确方法

为啥从自定义 UIView 向 UIButton 添加子视图不显示添加的子视图?

从 nib 加载 UITableViewCell 子类时给出的类型错误

在从 NIB 加载和 willMoveToSuperview 加载之间设置 UIImageView 子类:

iOS 8 中 Nib 加载的子视图的位置不正确