Es ist jetzt auf ios7.1 .__ behoben.
Tun Sie nichts, um das Problem zu beheben.
Anscheinend tritt das gleiche Problem erneut in iOS 8.0 und 8.1 auf
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.
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:
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:
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: -
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");
}
}
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.
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
}
}
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
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];
}
}
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.
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! :)
Ich habe immer noch das gleiche Problem in iOS 9.2
Ich bekam eine Lösung und posierte, da es anderen helfen könnte
Zählvariable erstellen, um zu verfolgen, wie oft die Methode aufgerufen wurde
int switchMethodCallCount = 0;
Speichern Sie den Bool-Wert für den Schaltwert
bool isSwitchOn = No;
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];
}
}
}
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
}
}
Das hat bei mir funktioniert.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
self.switch.isOn = true
}
DispatchQueue.main.async {
self.mySwitch.setOn(false, animated: true)
}
Dies funktioniert gut und ruft die Auswahlfunktion nicht erneut auf.