Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

Quiero añadir un nuevo UIButtonType personalizado a la clase UIButton a través de una categoría, así:

enum {
    UIButtonTypeMatteWhiteBordered = 0x100
};

@interface UIButton (Custom)

+ (id)buttonWithType:(UIButtonType)buttonType;

@end

¿Es posible conseguir la aplicación super de ese método reemplazado alguna manera?

+ (id)buttonWithType:(UIButtonType)buttonType {
    return [super buttonWithType:buttonType];
}

El código anterior no es válida desde super refiere a UIControl en este contexto.

¿Fue útil?

Solución

No, esto no es posible cuando se utiliza una categoría para aumentar una funcionalidad de clase, usted no es extendiéndose de la clase, en realidad está totalmente reemplazando el método existente, se pierde el método original < strong> completamente . Ido como el viento.

Si crea una subclase de UIButton, entonces esto es totalmente posible:

enum {
    UIButtonTypeMatteWhiteBordered = 0x100
};

@interface MyCustomButton : UIButton {}

@end

@implementation MyCustomButton 

+ (id)buttonWithType:(UIButtonType)buttonType {
    return [super buttonWithType:buttonType]; //super here refers to UIButton
}

@end

Otros consejos

Se puede sustituir el método en tiempo de ejecución con su propio método personalizado de este modo:

#import <objc/runtime.h>

@implementation UIButton(Custom)

// At runtime this method will be called as buttonWithType:
+ (id)customButtonWithType:(UIButtonType)buttonType 
{
    // ---Add in custom code here---

    // This line at runtime does not go into an infinite loop
    // because it will call the real method instead of ours. 
    return [self customButtonWithType:buttonType];
}

// Swaps our custom implementation with the default one
// +load is called when a class is loaded into the system
+ (void) load
{
    SEL origSel = @selector(buttonWithType:);

    SEL newSel = @selector(customButtonWithType:);

    Class buttonClass = [UIButton class];

    Method origMethod = class_getInstanceMethod(buttonClass, origSel);
    Method newMethod = class_getInstanceMethod(buttonClass, newSel);
    method_exchangeImplementations(origMethod, newMethod);
}

Tenga cuidado de cómo se utiliza esto, recuerde que sustituye a la aplicación por defecto para todos los usos UIButton sus aplicaciones. Además, lo hace anulación + carga, por lo que puede no funcionar para las clases que ya cuentan con un método de carga + y dependen de ella.

En su caso, es posible que así sea mejor simplemente la subclasificación UIButton.

Editar :. Como notas Tyler a continuación, ya que hay que utilizar un método de nivel de clase para hacer un botón que esto puede ser la única manera de creación de corrección

Jacob tiene un punto bueno que los métodos categoría actúan de manera diferente que los métodos de subclase. Manzana sugiere fuertemente que sólo se proporcionan métodos categoría que son completamente nuevo, porque hay varias cosas que pueden salir mal lo contrario -. Uno de los seres que la definición de un método categoría básicamente borra todas las demás implementaciones existentes del mismo nombre método

Por desgracia para lo que estamos tratando de hacer, UIButton parece estar diseñado específicamente para evitar la subclasificación. La forma única sancionada para obtener una instancia de un UIButton es a través de la [UIButton buttonWithType:] constructor. El problema con una subclase como Jacob sugiere (como este):

@implementation MyCustomButton 

+ (id)buttonWithType:(UIButtonType)buttonType {
  return [super buttonWithType:buttonType]; //super here refers to UIButton
}

@end

es que el tipo devuelto por [MyCustomButton buttonWithType:] seguirá siendo un UIButton, no MyCustomButton. Debido a que Apple no ha proporcionado ningún método init UIButton, no hay realmente una manera para que una subclase crear una instancia de sí mismo y ser inicializado correctamente como UIButton.

Si quieres algo de comportamiento personalizado, puede crear una subclase UIView personalizado que siempre contiene un botón como subvista, de modo que usted puede tomar ventaja de algunas de las funciones de UIButton.

Algo como esto:

@interface MyButton : UIView {}

- (void)buttonTapped;

@end

@implementation MyButton

-(id)initWithFrame:(CGRect)frame {
  if (self = [super initWithFrame:frame]) {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = self.bounds;
    [button addTarget:self action:@selector(buttonTapped)
     forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:button];
  }
  return self;
}

- (void)buttonTapped {
  // Respond to a button tap.
}

@end

Si desea que el botón para hacer cosas diferentes en función de las interacciones del usuario más complejos, se puede hacer más llamadas a [UIButton addTarget:action:forControlEvents:] para diferentes eventos de control.

Referencia: referencia de clase UIButton de Apple

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top