如何对UI元素进行子类化,如UILabel,UIButton



我正在CustomLabel class中子类化UILabel。当我尝试使用简单的UILabel时,我遇到了问题,我想在将来对其他元素进行子类化。我已经读到我可以创建一个UILabel category.这些东西哪个更好?类别还是子类?

这是我尝试子类的代码。它在setFont方法中失败。

@interface WPCustomLabel : UILabel
@property (strong, nonatomic) UIColor *color;
@property (strong, nonatomic) UIFont  *font;
@end
#import "WPCustomLabel.h"
@implementation WPCustomLabel
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}
-(void)setColor:(UIColor *)color
{
    self.color = color;
}
-(void)setFont:(UIFont *)font
{
    self.font = font;
}
@end

我在我的视图控制器中称之为自定义标签。

@property (strong, nonatomic) WPCustomLabel *titleLbl;
titleLbl = [[WPCustomLabel alloc] initWithFrame:CGRectMake(75, 25, 200, 14)];
[titleLbl setTextColor:[UIColor blackColor]];
[titleLbl setFont:[UIFont systemFontOfSize:14]];
[titleLbl setBackgroundColor:[UIColor clearColor]];
[titleLbl setText:@"Here I AM"];
[self.view addSubview:titleLbl];

如何对UI元素进行子类化,如UILabel,UIButton

没办法。

我已经读到我可以创建一个类别UILabel

没错。事实上,如果你想扩展类,你可能应该使用一个类别来代替(见前面的答案)。

它在 setFont 方法中失败。

您没有说明它是如何"失败"的,但我只能猜测它会导致无限递归和堆栈溢出/分段错误。那是因为

self.font = font;

等效于

[self setFont:font];

因此,您无条件地从自身内部调用该方法。

如果您不需要自定义这些属性的行为,只需不要管它们。 :)如果你这样做了,那么当你完成后,只需调用超类的实现:

- (void)setFont:(UIFont *)font
{
    [self doScaryCustomMagicStuff];
    [super setFont:font];
}

这实际上取决于您要实现的目标,类别不能具有属性,因此在您的示例中它们将不起作用。

在这里的问题是,在二传手中,你正在召回二传手:

-(void)setFont:(UIFont *)font
{
    self.font = font;
}

编译为(与以下相同):

-(void)setFont:(UIFont *)font
{
    [self setFont:font];
}

您应该能够看到此问题。一旦调用此方法,就无法摆脱此方法。您在这里混淆了属性和实例变量。重写资源库不应通过属性设置,而应直接设置到实例变量。所以:

// LOOK AT EDIT -- Do not do this for 'font'
-(void)setFont:(UIFont *)font
{
    _font = font;
}

编辑:

我没想清楚。由于您正在子类化UILabel因此您已经有一个font属性。你不应该直接指定它,因为你的超类(UILabel)已经有了它。因此,请摆脱该属性声明。话虽如此,如果不需要color,类别可能是更好的解决方案。无论如何,您可以像这样覆盖setFont:方法:

-(void)setFont:(UIFont *)font
{
    [super setFont:font];
    // do custom stuff
}

由于color不是UILabel属性,您应该通过实例变量(如上所示:_color = color)设置它,不要在此setter上调用super,因为UILabel不会响应它。

super调用是调用UILabel的实现,因为你是它的子类。

如果要扩展项目的功能,则应使用类别;例如向 UILabel 添加一个函数,应用程序中的任何 UILabel 都可以执行该函数。

但是,如果你想在应用的多个位置使用类似的 UILabel,那么你应该对 UILabel 进行子类化,在 initWithFrame 或 awakeFromNib 中相应地修改它,并在任何你想要的地方使用你的自定义实现。

在您的情况下,我建议将其子类化。标准UILabel中已经存在SetFont方法,您可以使用setTextColor而不是setColor。

我不知道

UIButton,但根据苹果的说法,UILabel可以通过子类自由定制。来自苹果文档:

基 UILabel 类为标签文本的简单样式和复杂样式提供支持。您还可以控制外观的各个方面,例如标签是使用阴影还是使用高光进行绘制。如果需要,您可以通过子类化进一步自定义文本的外观。

最新更新