wake-up-neo.com

iOS7 UISwitch sein Event ValueChanged: Ununterbrochenes Aufrufen dieses Fehlers oder was?

Bearbeiten

Es ist jetzt auf ios7.1 .__ behoben.
Tun Sie nichts, um das Problem zu beheben.

Edit2

Anscheinend tritt das gleiche Problem erneut in iOS 8.0 und 8.1 auf

Edit3

Es ist jetzt auf ios9.2 .__ behoben.
Tun Sie nichts, um das Problem zu beheben.


Hallo Heute habe ich gesehen in UISwitch's Ereignis ValueChanged: Aufruf von continuously, während ich On in Off oder Off in On ändere und mein Finger immer noch auf der rechten Seite sowie auf der linken Seite verschoben wurde. Ich habe ein GIF-Bild erstellt, um mit NSLog klarer zu sein.

enter image description here

Meine geänderte Methode ist:

- (IBAction)changeSwitch:(id)sender{

    if([sender isOn]){
        NSLog(@"Switch is ON");
    } else{
        NSLog(@"Switch is OFF");
    }

}

iOS6 derselbe Code von Switch funktioniert einwandfrei wie erwartet:

enter image description here

also kann mir jemand vorschlagen, dass nur einmal sein zustand ein- oder ausgeschaltet wird. oder ist das ein Fehler oder was ..?

UPDATE

Hier ist meine Demo davon:

programmatisch UISwitch hinzufügen

von XIB Hinzufügen von UISwitch

91
Nitin Gohel

Ich habe viele Benutzer mit dem gleichen Problem konfrontiert, also ist dies ein Fehler von UISwitch, also habe ich gerade eine provisorische Lösung gefunden. Ich habe eine gitHub-benutzerdefinierte KLSwitch-Anwendung für jetzt gefunden. Ich hoffe, Apple wird dies im nächsten Update von xCode beheben: -

https://github.com/KieranLafferty/KLSwitch

7
Nitin Gohel

Bitte sehen Sie den folgenden Code:

-(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");
    }
}
44
AeroStar

Gleicher Fehler hier. Ich glaube, ich habe eine einfache Problemumgehung gefunden. Wir müssen nur eine neue BOOL verwenden, die den vorherigen Zustand der UISwitch und eine if -Anweisung in unserer IBAction (Value Changed fired) speichert, um zu überprüfen, ob der Wert des Switch tatsächlich geändert wurde.

previousValue = FALSE;

[...]

-(IBAction)mySwitchIBAction {
    if(mySwitch.on == previousValue)
        return;
    // resetting the new switch value to the flag
    previousValue = mySwitch.on;
 }

Keine seltsamen Verhaltensweisen mehr. Ich hoffe es hilft.

12
nnarayann

Sie können die .selected-Eigenschaft von UISwitch verwenden, um sicherzustellen, dass Ihr Code nur einmal ausgeführt wird, wenn sich der Wert tatsächlich ändert. Ich denke, dass dies eine großartige Lösung ist, da keine Unterklassen oder Hinzufügen neuer Eigenschaften erforderlich sind.

 //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
    }
}

Und hier ist es in Swift: 

func doToggle(switch: UISwitch) {
    if switch.on && !switch.selected {
        switch.selected = true
        // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
    } else {
        switch.selected = false
    }
}
12
itsji10dra

Wenn Sie so viele Switches in Ihrer App verwenden, besteht ein Problem darin, den Code an allen Stellen zu ändern, an denen die T -Aktionsmethode von UISwitch definiert ist. Sie können die Ereignisse nur bei Wertänderungen ändern und handhaben.

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

Wir ignorieren Ereignisse, wenn der Wert mit dem geänderten Wert übereinstimmt. Setzen Sie CustomSwitch in der gesamten UISwitch-Klasse im Storyboard. Dadurch wird das Problem gelöst und das Ziel wird nur einmal aufgerufen, wenn sich der Wert ändert 

9
codester

Wenn Sie nicht sofort auf die Wertänderung des Schalters reagieren müssen, kann dies folgende Lösung sein:

- (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];
  }
}
6
pre

Dieses Problem ist noch in der Beta von iOS 9.3 vorhanden. Wenn Sie nichts dagegen haben, dass der Benutzer nicht außerhalb des Schalters ziehen kann, finde ich, dass die Verwendung von .TouchUpInside anstelle von .ValueChanged zuverlässig funktioniert.

3
Nick Kohrn

Dieses Problem plagt mich, wenn ich den Schalter an andere Verhaltensweisen knüpfe. Im Allgemeinen gehen Dinge nicht gerne von on zu on. Hier ist meine einfache Lösung:

@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
}

Stellen Sie sicher, dass Sie bei jeder manuellen Änderung von self.lastSwitchState auch mySwitch.on einstellen! :)

2
Ben Leggiero

Ich habe immer noch das gleiche Problem in iOS 9.2 

Ich bekam eine Lösung und posierte, da es anderen helfen könnte 

  1. Zählvariable erstellen, um zu verfolgen, wie oft die Methode aufgerufen wurde

    int switchMethodCallCount = 0;
    
  2. Speichern Sie den Bool-Wert für den Schaltwert

    bool isSwitchOn = No;
    
  3. Führen Sie in der Wertänderungsmethode von Switch die Wunschaktion nur für den ersten Methodenaufruf aus. Wenn der Wert des Schalters erneut geändert wird, setzen Sie den Zählwert und den Wert der Bool-Variablen auf den Standard

    - (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];
    
    
        }
    }
    
    
    }
    
2
Chetan Koli

Diese Art von Problem wird häufig durch ValueChanged verursacht. Sie müssen die Taste nicht drücken, um die Funktion auszuführen. Es ist kein Touch-Event. Jedes Mal, wenn Sie den Schalter programmgesteuert auf Ein/Aus ändern, ändert sich der Wert und es wird erneut die IBAction-Funktion aufgerufen. 

@RoNiT hatte die richtige Antwort mit:

Schnell 

func doToggle(switch: UISwitch) {
    if switch.on && !switch.selected {
        switch.selected = true
        // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
    } else {
        switch.selected = false
    }
}
1
Dave G

Das hat bei mir funktioniert.

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
    self.switch.isOn = true
}
0
user3305074
DispatchQueue.main.async {
        self.mySwitch.setOn(false, animated: true)
    }

Dies funktioniert gut und ruft die Auswahlfunktion nicht erneut auf.

0
anuraagdjain