El evento de cambio UISegmentedControl no se activa en iOS5

Tengo un UISegmentedControl cuyo evento "Valor cambiado" está conectado en Interface Builder para llamar a mi controlador -(IBAction)segmentChangeAction:(id)sender;

Cuando el usuario toca el control para cambiar el segmento seleccionado, como se esperaba segmentChangeAction se llama ya sea en iOS4 o iOS5.

Cuando cambio programáticamente el segmento seleccionado a través de segmentedControl.selectedSegmentIndex = newIndex;, en iOS4 segmentChangeAction se llama y el segmento refleja la nueva selección. Sin embargo en iOS5 segmentChangeAction is no llamado, sin embargo, el segmento refleja la nueva selección.

¿Es esto un cambio en iOS5? ¿Hay algo que pueda hacer para conseguir segmentChangeAction llamado en iOS5 cuando cambio programáticamente la selección?

preguntado el 08 de noviembre de 11 a las 17:11

2 Respuestas

Este es un cambio en iOS 5 para UISegmentedControl para ser coherente con todos los demás controles.

La idea es que la acción solo se active automáticamente como resultado de la interacción del usuario. Antes de iOS 5, UISegmentedControlLas acciones de este se activarían debido a la interacción del usuario. y interacción programática. Sin embargo, iniciar el cambio mediante programación significa que también puede hacer [myControl sendActionsForControlEvents:UIControlEventValueChanged] tú mismo.

Sin embargo, debes tener cuidado con esto. Di que haces:

[segmentedControl setSelectedSegmentIndex:newIndex];
[segmentedControl sendActionsForControlEvents:UIControlEventValueChanged];

Si crea y ejecuta esto en iOS 5, funciona como espera. Si compila y ejecuta esto en iOS 4, sus acciones se dispararán dos veces (una vez cuando tu setSelectedSegmentIndex y de nuevo cuando tu sendActions...).

La forma de evitar esto es hacer una especie de guardia. Esto podría ser una verificación de tiempo de ejecución para indicar que está ejecutando un dispositivo iOS 5+, o incluso podría ser algo más mundano, como esto:

// changingIndex is a BOOL ivar
changingIndex = YES;
[segmentedControl setSelectedSegmentIndex:newIndex];
changingIndex = NO;
[segmentedControl sendActionsForControlEvents:UIControlEventValueChanged];

y luego en tu método de acción ...

- (void)segmentedControlSelectedIndexChanged:(id)sender {
  if (!changingIndex) {
    // your action code here, guaranteed to only run as a result of the sendActions... msg
  }
}

respondido 08 nov., 11:21

¡Gracias por la explicación detallada! He hecho la cosa más simple (llamar segmentChangeAction directamente después de cambiar el índice), habiendo verificado que no hay problema con que este código se llame dos veces en iOS <5. Pero me siento mucho más feliz sabiendo por qué tuve que hacer esto, gracias. - Clafou

@Vin no este año; Estoy demasiado ocupado para prestarle la atención que se merece ser un moderador. - Dave DeLong

@Clafou de nada! Y si encuentras un UIControl Eso hace no sigue este comportamiento, por favor presentar un error y se arreglará. :) - Dave DeLong

@Dave eso es malo ... parece que este año tampoco tendremos a nadie de iOS u objetivo c :( - Vin

@Vin Brad Larson, BoltClock y Moshe han sido nominados y todos están activos en las etiquetas relacionadas con Cocoa. - Dave DeLong

Encontré otra forma, probablemente un poco más fácil de entender, puede extender UISegmentedControl y agregar la acción de destino en los métodos de inicio y llamar a un método delegado para activar el cambio de valor

aquí está el código de ejemplo

el archivo de encabezado se ve así

#import <UIKit/UIKit.h>
@class CGUISegmentedControl;

@protocol CGUISegmentedControlDelegate <NSObject>

@optional
- (void) segmentedControl:(CGUISegmentedControl *) control valueChangedTo:(NSInteger) nValue;

@end

@interface CGUISegmentedControl : UISegmentedControl

@property (nonatomic,unsafe_unretained) id <CGUISegmentedControlDelegate> delegate;

@end

archivo .m

    #import "CGUISegmentedControl.h"

@implementation CGUISegmentedControl

@synthesize delegate                = _delegateAction;

- (void) addTargetAction {

    [self addTarget:self action:@selector(indexChanged:) forControlEvents:UIControlEventValueChanged];

}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addTargetAction];
    }
    return self;
}

- (id) initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder:aDecoder];
    if (self) {
        [self addTargetAction];
    }
    return self;

}

- (id) initWithItems:(NSArray *)items {

    self = [super initWithItems:items];
   if (self) {
        [self addTargetAction];
    }
    return self;
}

- (id) init {

    self = [super init];
    if (self) {
        [self addTargetAction];
    }
    return self;

}

- (void) indexChanged:(id) sender {

    if (_delegateAction && [_delegateAction respondsToSelector:@selector(segmentedControl:valueChangedTo:)])
        [_delegateAction segmentedControl:self valueChangedTo:self.selectedSegmentIndex];


}

@end

Y puede configurar el delegado en la clase de llamada

Respondido 16 Oct 12, 15:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.