3

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

这是我试图子类化的代码。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

我在我的 ViewController 中调用了这个 CustomLabel。

@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];
4

4 回答 4

3

如何子类化 UI 元素,如 UILabel、UIButton

绝不。

我读过我可以创建一个类别UILabel

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

它在 setFont 方法中失败。

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

self.font = font;

相当于

[self setFont:font];

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

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

- (void)setFont:(UIFont *)font
{
    [self doScaryCustomMagicStuff];
    [super setFont:font];
}
于 2013-10-30T15:07:14.183 回答
3

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

您的问题是,在设置器中,您正在调用设置器:

-(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:),不要在此设置器上调用 super ,因为UILabel不会响应它。

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

于 2013-10-30T15:09:55.283 回答
0

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

但是,如果你想在你的应用程序的几个地方使用类似的 UILabel,那么你应该继承 UILabel,在 initWithFrame 或 awakeFromNib 中相应地修改它,并在任何你想要的地方使用你的自定义实现。

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

于 2013-10-30T15:06:04.827 回答
0

我不知道 UIButton,但根据 Apple UILabel 可以通过子类化自由定制。来自 Apple 文档:

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

于 2016-09-07T13:01:12.990 回答