Cómo subclass elementos de UI como UILabel, UIButton

Estoy subclassando una UILabel en una CustomLabel class . Tengo problemas cuando trato de usar un UILabel simple y me gustaría UILabel otros elementos en un futuro. He leído que puedo crear una category de UILabel . ¿Cuál de estas cosas es mejor? categoría o subclass?

Aquí está mi código tratando de subclass. Fracasa en el método 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 

y llamo a este CustomLabel en mi 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]; 

Cómo subclass elementos de UI como UILabel, UIButton

De ninguna manera.

He leído que puedo crear una categoría de UILabel

Está bien. De hecho, si desea ampliar la class, probablemente debería usar una categoría en su lugar (consulte la respuesta anterior).

Fracasa en el método setFont.

No dijiste cómo "falla", pero todo lo que puedo adivinar es que provoca una recursión infinita y una falla de desbordamiento / segmentación de stack como resultado. Eso es porque

 self.font = font; 

es equivalente con

 [self setFont:font]; 

Entonces llamas al método desde dentro, incondicionalmente.

Si no necesita personalizar el comportamiento de esas properties, simplemente déjelas en paz. 🙂 Si lo hace, invoque la implementación de la superclass cuando termine:

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

Realmente depende de lo que esté tratando de lograr, las categorías no pueden tener properties, por lo que en su ejemplo no funcionarán.

Tu problema aquí es que en los setters estás recordando a los setters:

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

comstack a (es el mismo que):

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

Debería poder ver este problema. No se puede salir de este método una vez que lo llamas. Estás confundiendo properties y variables de instancia aquí. Anular organizadores no debe establecer a través de la propiedad, sino más bien directamente a la variable de instancia. Asi que:

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

EDITAR:

No estaba pensando bien. Como estás subclassando UILabel , ya tienes una propiedad de font . No debe especificar esto directamente ya que su súper class ( UILabel ) ya lo tiene. Así que deshágase de las declaraciones de properties. Dicho esto, si no se necesita color , una categoría probablemente sea una mejor solución para usted. Independientemente, puede anular su método setFont: así:

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

Y dado que el color no es una propiedad UILabel , debe configurarlo a través de la variable de instancia (como anteriormente: _color = color ), no llame a super en este UILabel ya que UILabel no responde.

La super llamada está llamando a la implementación de UILabel ya que eres una subclass de eso.

Debe usar las categorías si desea ampliar la funcionalidad de un artículo; como agregar una function a UILabel que cualquier UILabel en su aplicación puede realizar.

Pero, si desea UILabels similares en varios lugares de su aplicación, que debe subclass UILabel, modifíquelo en consecuencia dentro de initWithFrame o awakeFromNib y use su implementación personalizada donde lo desee.

En su caso, sugiero subclasificarlo. El método SetFont ya existe en UILabel estándar y puede usar setTextColor en lugar de setColor.

No sé acerca de UIButton, pero según Apple, UILabel puede personalizarse libremente subclassando. De la documentation de Apple:

La class base UILabel proporciona soporte tanto para el estilo simple como complejo del text de la label. También puede controlar los aspectos de apariencia, como si la label utiliza una sombra o dibuja con un resaltado. Si es necesario, puede personalizar aún más la apariencia de su text mediante subclasss.