Il est maintenant fixé sur ios7.1
Ne faites pas de tweak pour le réparer.
Apparemment, le même problème se reproduit dans iOS 8.0 et 8.1
Il est maintenant fixé sur ios9.2
Ne faites pas de tweak pour le réparer.
Bonjour, j’ai vu dans UISwitch's
Evénement ValueChanged:
Appeler continuously
alors que je suis passé à On
à Off
ou Off
à On et mon doigt s’est déplacé toujours du côté droit au côté gauche. J'ai créé une image GIF pour plus de clarté avec NSLog.
La méthode Ma valeur modifiée est:
- (IBAction)changeSwitch:(id)sender{
if([sender isOn]){
NSLog(@"Switch is ON");
} else{
NSLog(@"Switch is OFF");
}
}
iOS6 le même code de commutateur fonctionne bien comme nous l'attendions:
alors quelqu'un peut-il me suggérer d'appeler une seule fois son état On ou Off. ou est-ce un bug ou quoi ..?
METTRE À JOUR
Voici ma démo:
J'ai eu beaucoup d'utilisateurs qui font face au même problème alors peut-être que c'est un bogue de UISwitch
alors j'ai trouvé tout à l'heure une solution temporaire. J'ai trouvé un gitHub
personnalisé KLSwitch
utiliser ceci pour le moment, j'espère que Apple corrigera cela dans la prochaine mise à jour de xCode: -
S'il vous plaît voir le code suivant:
-(void)viewDidLoad
{
[super viewDidLoad];
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(130, 235, 0, 0)];
[mySwitch addTarget:self action:@selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:mySwitch];
}
- (void)changeSwitch:(id)sender{
if([sender isOn]){
NSLog(@"Switch is ON");
} else{
NSLog(@"Switch is OFF");
}
}
Même bug ici. Je pense avoir trouvé une solution de contournement simple. Nous devons simplement utiliser une nouvelle BOOL
qui stocke l’état précédent de la UISwitch
et une instruction if dans notre IBAction
(valeur modifiée), pour vérifier que la valeur du commutateur a réellement changé.
previousValue = FALSE;
[...]
-(IBAction)mySwitchIBAction {
if(mySwitch.on == previousValue)
return;
// resetting the new switch value to the flag
previousValue = mySwitch.on;
}
Pas plus de comportements étranges. J'espère que ça aide.
Vous pouvez utiliser la propriété .selected
de la UISwitch
'pour vous assurer que votre code ne s'exécute qu'une fois lorsque la valeur réelle est modifiée. Je pense que c'est une excellente solution car elle évite d'avoir à sous-classer ou à ajouter de nouvelles propriétés.
//Add action for `ValueChanged`
[toggleSwitch addTarget:self action:@selector(switchTwisted:) forControlEvents:UIControlEventValueChanged];
//Handle action
- (void)switchTwisted:(UISwitch *)twistedSwitch
{
if ([twistedSwitch isOn] && (![twistedSwitch isSelected]))
{
[twistedSwitch setSelected:YES];
//Write code for SwitchON Action
}
else if ((![twistedSwitch isOn]) && [twistedSwitch isSelected])
{
[twistedSwitch setSelected:NO];
//Write code for SwitchOFF Action
}
}
Et le voici à Swift:
func doToggle(switch: UISwitch) {
if switch.on && !switch.selected {
switch.selected = true
// SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
} else {
switch.selected = false
}
}
Si vous utilisez autant de commutateurs dans votre application, vous rencontrez des difficultés pour modifier le code dans tous les emplacements où la méthode d'action t De UISwitch est définie. Vous pouvez créer un commutateur personnalisé et gérer les événements uniquement si la valeur change.
CustomSwitch.h
#import <UIKit/UIKit.h>
@interface Care4TodayCustomSwitch : UISwitch
@end
CustomSwitch.m
@interface CustomSwitch(){
BOOL previousValue;
}
@end
@implementation CustomSwitch
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
previousValue = self.isOn;
}
return self;
}
-(void)awakeFromNib{
[super awakeFromNib];
previousValue = self.isOn;
self.exclusiveTouch = YES;
}
- (void)setOn:(BOOL)on animated:(BOOL)animated{
[super setOn:on animated:animated];
previousValue = on;
}
-(void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{
if(previousValue != self.isOn){
for (id targetForEvent in [self allTargets]) {
for (id actionForEvent in [self actionsForTarget:targetForEvent forControlEvent:UIControlEventValueChanged]) {
[super sendAction:NSSelectorFromString(actionForEvent) to:targetForEvent forEvent:event];
}
}
previousValue = self.isOn;
}
}
@end
Nous ignorons les événements si la valeur est identique à la valeur modifiée. Placez CustomSwitch dans toute la classe d'UISwitch dans le storyboard. Cela résoudra le problème et n'appellera la cible qu'une seule fois lorsque la valeur sera modifiée.
Si vous n'avez pas besoin de réagir instantanément au changement de valeur du commutateur, voici une solution:
- (IBAction)switchChanged:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if ([switch isOn]) {
[self performSelector:@selector(enable) withObject:nil afterDelay:2];
} else {
[self performSelector:@selector(disable) withObject:nil afterDelay:2];
}
}
Ce problème est toujours là depuis iOS 9.3 beta. Si cela ne vous dérange pas que l'utilisateur ne puisse pas glisser en dehors du commutateur, l'utilisation de .TouchUpInside
plutôt que .ValueChanged
fonctionne de manière fiable.
Ce problème me tourmente lorsque je lie le passage à d’autres comportements. Généralement, les choses ne vont pas de on
à on
. Voici ma solution simple:
@interface MyView : UIView
@parameter (assign) BOOL lastSwitchState;
@parameter (strong) IBOutlet UISwitch *mySwitch;
@end
@implementation MyView
// Standard stuff goes here
- (void)mySetupMethodThatsCalledWhenever
{
[self.mySwitch addTarget:self action:@selector(switchToggled:) forControlEvents:UIControlEventValueChanged];
}
- (void)switchToggled:(UISwitch *)someSwitch
{
BOOL newSwitchState = self.mySwitch.on;
if (newSwitchState == self.lastSwitchState)
{
return;
}
self.lastSwitchState = newSwitchState;
// Do your thing
}
Veillez simplement à définir également self.lastSwitchState
chaque fois que vous modifiez manuellement mySwitch.on
! :)
Je suis toujours confronté au même problème dans iOS 9.2
J'ai eu la solution et posant comme cela pourrait aider les autres
Créer une variable de comptage pour tracer le nombre d'appels de la méthode
int switchMethodCallCount = 0;
Enregistrer la valeur booléenne pour la valeur de commutation
bool isSwitchOn = No;
Dans la méthode de changement de valeur de Switch, effectuez l'action souhaitée pour le premier appel de méthode uniquement. Lorsque la valeur du commutateur change à nouveau, définissez la valeur de comptage et la valeur de variable bool sur la valeur par défaut
- (IBAction)frontCameraCaptureSwitchToggle:(id)sender {
//This method will be called multiple times if user drags on Switch,
//But desire action should be perform only on first call of this method
//1. 'switchMethodCallCount' variable is maintain to check number of calles to method,
//2. Action is peform for 'switchMethodCallCount = 1' i.e first call
//3. When switch value change to another state, 'switchMethodCallCount' is reset and desire action perform
switchMethodCallCount++ ;
//NSLog(@"Count --> %d", switchMethodCallCount);
if (switchMethodCallCount == 1) {
//NSLog(@"**************Perform Acction******************");
isSwitchOn = frontCameraCaptureSwitch.on
[self doStuff];
}
else
{
//NSLog(@"Do not perform");
if (frontCameraCaptureSwitch.on != isSwitchOn) {
switchMethodCallCount = 0;
isSwitchOn = frontCameraCaptureSwitch.on
//NSLog(@"Count again start");
//call value change method again
[self frontCameraCaptureSwitchToggle:frontCameraCaptureSwitch];
}
}
}
Ce type de problème est souvent causé par ValueChanged. Vous n'avez pas besoin d'appuyer sur le bouton pour que la fonction s'exécute. Ce n'est pas un événement tactile. Chaque fois que vous réglez le commutateur sur ON/OFF par programmation, la valeur change et il appelle à nouveau la fonction IBAction.
@RoNiT avait la bonne réponse avec:
Rapide
func doToggle(switch: UISwitch) {
if switch.on && !switch.selected {
switch.selected = true
// SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
} else {
switch.selected = false
}
}
Cela a fonctionné pour moi.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
self.switch.isOn = true
}
DispatchQueue.main.async {
self.mySwitch.setOn(false, animated: true)
}
Cela fonctionne bien et n'appelle pas à nouveau la fonction de sélection.