问题
I am subclassing an UILabel
in a CustomLabel class
. I have problems when I try to use a simple UILabel
and I will like to subclass other elements in a future. I have read that I can create a category
of UILabel
. Which of this things is better? category or subclass?
Here is my code trying to subclass. It fails in setFont
method.
@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
and I call this CustomLabel in my ViewController.
@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];
回答1:
How to Subclass UI elements like UILabel, UIButton
In no way.
I have read that I can create a category of
UILabel
That's right. In fact, if you want to extend the class, you should probably use a category instead (see the previous answer).
It fails in setFont method.
You didn't state how it "fails", but all I can guess is it causes infinite recursion and a stack overflow/segmentation fault as a result. That's because
self.font = font;
is equivalent with
[self setFont:font];
So you are calling the method from within itself, unconditionally.
If you don't need to customize the behavior of those properties, just leave'em alone. :) If you do, then just invoke the implementation of the superclass when you're done:
- (void)setFont:(UIFont *)font
{
[self doScaryCustomMagicStuff];
[super setFont:font];
}
回答2:
It really depends what you are trying to achieve, categories cannot have properties though so in your example they would not work.
Your issue here is that in the setters you are recalling the setters:
-(void)setFont:(UIFont *)font
{
self.font = font;
}
compiles to (is the same as):
-(void)setFont:(UIFont *)font
{
[self setFont:font];
}
You should be able to see this problem. There is no getting out of this method once you call it. You are confusing properties and instance variables here. Overriding setters should not set via the property but rather directly to the instance variable. So:
// LOOK AT EDIT -- Do not do this for 'font'
-(void)setFont:(UIFont *)font
{
_font = font;
}
EDIT:
I was not thinking straight. Since you are subclassing UILabel
you already have a font
property. You should not specify this directly since your super class (UILabel
) already has it. So get rid of that property declarations. That being said, if color
is not needed, a category will probably be a better solution for you. Regardless, you can override your setFont:
method like this:
-(void)setFont:(UIFont *)font
{
[super setFont:font];
// do custom stuff
}
And since color
is not a UILabel
property you should set it via the instance variable (like above: _color = color
), do not call super on this setter since UILabel
does not respond to it.
The super
call is calling UILabel
's implementation since you are a subclass of that.
回答3:
You should use the categories if you want to extend the functionality of an item; like adding a function to UILabel which any UILabel in your application can perform.
But, if you want similar UILabels in several places of your app, than you should subclass UILabel, modify it accordingly inside initWithFrame or awakeFromNib and use your custom implementation wherever you want it.
In your case I suggest subclassing it. SetFont method already exists in standard UILabel and you can use setTextColor instead of setColor.
回答4:
I don't know about UIButton, but according to Apple UILabel may be freely customized by subclassing. From Apple documentation:
The base UILabel class provides support for both simple and complex styling of the label text. You can also control over aspects of appearance, such as whether the label uses a shadow or draws with a highlight. If needed, you can customize the appearance of your text further by subclassing.
来源:https://stackoverflow.com/questions/19686275/how-to-subclass-ui-elements-like-uilabel-uibutton