Subclass UIButton para agregar una propiedad

Me gustaría subclass UIButton para agregar algunas properties que necesito (no methods … solo properties).

Aquí el código de mi subclass:

 //.h----------------------- @interface MyButton : UIButton{ MyPropertyType *property; } @property (nonatomic,retain) MyPropertyType *property; @end //.m-------------------------- @implementation MyButton @synthesize property; @end 

Y aquí cómo uso la class:

 MyButton *btn = ((MytButton *)[MyButton buttonWithType:UIButtonTypeRoundedRect]); btn.property = SomeDataForTheProperty; 

De donde obtengo este error:

  -[UIRoundedRectButton setProperty:]: unrecognized selector sent to instance 0x593e920 

Por lo tanto, desde ButtonWithType UIRoundedRectButton un UIRoundedRectButton y (Mybutton *) no puede (Mybutton *) … ¿Qué MyButton hacer para get un object MyButton ? es -init la solución única?

¡Gracias!

Intenta utilizar una categoría con references asociativas en su lugar. Es mucho más limpio y funcionará en todas las instancias de UIButton .

UIButton + Propiedad.h

 #import <Foundation/Foundation.h> @interface UIButton(Property) @property (nonatomic, retain) NSObject *property; @end 

UIButton + Property.m

 #import "UIButton+Property.h" #import <objc/runtime.h> @implementation UIButton(Property) static char UIB_PROPERTY_KEY; @dynamic property; -(void)setProperty:(NSObject *)property { objc_setAssociatedObject(self, &UIB_PROPERTY_KEY, property, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -(NSObject*)property { return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY); } @end 

// Ejemplo de uso

 #import "UIButton+Property.h" ... UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button1.property = @"HELLO"; NSLog(@"Property %@", button1.property); button1.property = nil; NSLog(@"Property %@", button1.property); 

Necesitas hacer:

 MyButton *btn = [[MyButton alloc] init]; 

Para crear tu button. The buttonWithType:UIButtonTypeRoundedRect solo crea objects de UIButton.

=== editar ===

Si desea usar el button RoundedRect; entonces sugiero lo siguiente. Básicamente, creamos una UIView con cualquier propiedad que queramos y agregamos el button deseado a esa vista.


.marido

 @interface MyButton : UIView { int property; } @property int property; @end 

.metro

 @implementation MyButton @synthesize property; - (id)initWithFrame:(CGRect)_frame { self = [super initWithFrame:_frame]; if (self) { UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; btn.frame = self.bounds; [self addSubview:btn]; } return self; } @end 

Uso:

 MyButton *btn = [[MyButton alloc] initWithFrame:CGRectMake(0, 0, 200, 20)]; btn.property = 42; [self.view addSubview:btn]; 

Tengo un esquema simple que solo implica unos pocos methods de biblioteca, sin repeticiones, y solo 3 líneas de código para cada propiedad que desee agregar. A continuación se incluyen dos properties de ejemplo: startPoint y tileState. A modo ilustrativo, estas son las líneas que debería agregar para una propiedad como tileState:

 //@property (assign, nonatomic) SCZTileState tileState; // tileState line 1 //@property (assign, nonatomic) SCZTileState tileState; // tileState line 2 //@dynamic tileState; // tileState line 3 

Hay más detalles en mi blog que describe cómo funciona esto.

UIButton + SCZButton.h

 #import <UIKit/UIKit.h> @interface UIButton (SCZButton) @property (readwrite, nonatomic) id assocData; @end 

UIButton + SCZButton.m

 // UIButton+SCZButton.m // Copyright (c) 2013 Ooghamist LLC. All rights reserved. #import "UIButton+SCZButton.h" #import <objc/runtime.h> @implementation UIButton (SCZButton) - (id)assocData { id data = objc_getAssociatedObject(self, "SCZButtonData"); return data; } - (void)setAssocData:(id)data { objc_setAssociatedObject(self, "SCZButtonData", data, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end 

OOGTotallyTile.h

 // UIButton+OOGTotallyTile.m // Copyright (c) 2013 Ooghamist LLC. All rights reserved. #import <UIKit/UIKit.h> #import "UIButton+SCZButton.h" #define kPointLabelTag 837459 typedef enum { SCZTileStatePlaced, SCZTileStateDropping, SCZTileStateDropped } SCZTileState; @interface SCZButtonData : NSObject @property (assign, nonatomic) CGPoint startPoint; @property (assign, nonatomic) SCZTileState tileState; // tileState line 1 @end @interface UIButton (OOGTotallyTile) @property (readonly, nonatomic) SCZButtonData *buttonData; @property (assign, nonatomic) CGPoint startPoint; @property (assign, nonatomic) SCZTileState tileState; // tileState line 2 @end 

OOGTotallyTile.m

 // UIButton+OOGTotallyTile.m // Copyright (c) 2013 Ooghamist LLC. All rights reserved. #import "OOGTotallyTile.h" @implementation SCZButtonData @end @implementation UIButton (OOGTotallyTile) @dynamic startPoint; @dynamic tileState; // tileState line 3 - (SCZButtonData*)buttonData { if ( ! self.assocData) { self.assocData = [[SCZButtonData alloc] init]; } return self.assocData; } - (id)forwardingTargetForSelector:(SEL)aSelector { id forwardingTarget = [super forwardingTargetForSelector:aSelector]; if ( ! forwardingTarget) { return [self buttonData]; } return forwardingTarget; } @end