Ios 如何对UI元素(如UILabel、UIButton)进行子类化

Ios 如何对UI元素(如UILabel、UIButton)进行子类化,ios,iphone,objective-c,uilabel,subclass,Ios,Iphone,Objective C,Uilabel,Subclass,我正在CustomLabel类中对UILabel进行子类化。当我尝试使用一个简单的UILabel时,我遇到了一些问题,我希望将来对其他元素进行子类化。我已经读到我可以创建UILabel的类别。这些东西中哪一个更好?类别还是子类 下面是我试图创建子类的代码。它在setFont方法中失败 @interface WPCustomLabel : UILabel @property (strong, nonatomic) UIColor *color; @property (strong, nonato

我正在
CustomLabel类中对
UILabel
进行子类化。当我尝试使用一个简单的
UILabel
时,我遇到了一些问题,我希望将来对其他元素进行子类化。我已经读到我可以创建
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];

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

但是,如果您希望在应用程序的多个位置使用类似的UILabel,那么您应该将UILabel子类化,在initWithFrame或awakeFromNib中相应地修改它,并在任何需要的地方使用自定义实现

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

如何对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;
}
编译为(与相同):

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

// 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
属性,您应该通过实例变量设置它(如上所述:
\u color=color
),因此不要在此设置器上调用super,因为
UILabel
不会响应它


super
调用正在调用
UILabel
的实现,因为您是其中的一个子类。

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

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


问题是什么?字体未应用或其他任何内容?为什么要覆盖
setColor:
setFont:
?你的方法没有做任何有用的事情。如果你直接重新分配IVAR,最好调用
[super-setFont:font]
,或者至少用
[self-willChangeValueForKey:@“font”]
[self-didChangeValueForKey:@“font”]
警告KVC。@Cyrille你看过我的编辑吗?我会修改我原来的一个,使它更清楚了。
-(void)setFont:(UIFont *)font
{
    [super setFont:font];
    // do custom stuff
}