36 votes

Evénement de modification UISegmentedControl non déclenché dans iOS5

J'ai un UISegmentedControl dont la Valeur a changé" événement est câblée à l'Interface Builder pour appeler mon contrôleur -(IBAction)segmentChangeAction:(id)sender;

Lorsque l'utilisateur appuie sur la commande pour modifier le segment sélectionné, comme prévu, segmentChangeAction est appelé que dans iOS4 ou iOS5.

Quand je l'ai changer par programmation le segment sélectionné par segmentedControl.selectedSegmentIndex = newIndex;, sur iOS4 segmentChangeAction est appelée et le secteur reflète la nouvelle sélection. Cependant sur iOS5 segmentChangeAction est pas appelé, mais le segment de ne tenir compte de la nouvelle sélection.

Est-ce un changement dans iOS5? Est-ce que je peux faire pour obtenir l' segmentChangeAction appelé sur iOS5 quand je l'ai changer par programmation de la sélection?

70voto

Dave DeLong Points 156978

C'est un changement dans iOS 5 pour UISegmentedControl pour être compatible avec tous les autres contrôles.

L'idée est que l'action ne devrait déclenché automatiquement lors de l'interaction de l'utilisateur. Avant iOS 5, UISegmentedControls'actions serait congédié en raison de l'interaction de l'utilisateur et programmatique de l'interaction. Cependant, d'initier le changement par programme signifie que vous pouvez également faire [myControl sendActionsForControlEvents:UIControlEventValueChanged] vous-même.

Cependant, vous devez être prudent avec cette. Dire que vous faites:

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

Si vous générez et exécutez cette sur iOS 5, il fonctionne comme prévu. Si vous générez et exécutez cette sur iOS 4, vous aurez vos actions tiré deux fois (une fois lors de l' setSelectedSegmentIndex et à nouveau lorsque vous sendActions...).

Le moyen de contourner cela est de faire une sorte de garde. Cela pourrait être un moment de l'exécution pour indiquer que vous êtes en cours d'exécution sur un iOS 5+ appareil, ou peut-être même quelque chose de plus terre à terre, comme ceci:

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

et puis dans votre méthode d'action...

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

5voto

Chamira Fernando Points 1984

J'ai trouvé un autre moyen, probablement un peu plus facile à comprendre, que vous pouvez étendre UISegmentedControl et ajouter une action cible dans les méthodes init et appeler une méthode déléguée pour déclencher le changement de valeur.

voici l'exemple de code

fichier d'en-tête ressemble à ceci

 #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
 

fichier .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
 

Et vous pouvez définir le délégué dans la classe d'appel

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X