Edytować
Jest teraz naprawiony ios7.1
Nie rób żadnych poprawek, aby to naprawić.
Edycja 2
Najwyraźniej ten sam problem występuje ponownie w iOS 8.0 i 8.1
Edycja3
Jest teraz naprawiony ios9.2
Nie rób żadnych poprawek, aby to naprawić.
Hi Dziś widziałem w UISwitch's
Event ValueChanged:
Wywołanie continuously
podczas gdy jestem na zmianę On
do Off
lub Off
na On i mój palec przeniósł nadal po prawej stronie, jak również po lewej stronie. Dodałem obraz GIF, aby był bardziej przejrzysty dzięki NSLog.
Metoda „Zmiana wartości” to:
- (IBAction)changeSwitch:(id)sender{
if([sender isOn]){
NSLog(@"Switch is ON");
} else{
NSLog(@"Switch is OFF");
}
}
iOS6 ten sam kod Switch działa dobrze, jak się spodziewamy:
więc może ktoś zasugerować mi, że wywołanie tylko raz jego stan jest włączony lub wyłączony. czy to jest błąd czy co ..?
AKTUALIZACJA
Oto moje demo:
Odpowiedzi:
Zobacz poniższy kod:
-(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"); } }
źródło
Ten sam błąd tutaj. Myślę, że znalazłem proste obejście. Musimy po prostu użyć nowej,
BOOL
która przechowuje poprzedni stan instrukcjiUISwitch
i if w naszymIBAction
(uruchomiono wartość zmieniona), aby sprawdzić, czy wartość przełącznika faktycznie się zmieniła.previousValue = FALSE; [...] -(IBAction)mySwitchIBAction { if(mySwitch.on == previousValue) return; // resetting the new switch value to the flag previousValue = mySwitch.on; }
Nigdy więcej dziwnych zachowań. Mam nadzieję, że to pomoże.
źródło
Możesz użyć właściwości
UISwitch
's,.selected
aby upewnić się, że kod zostanie wykonany tylko raz, gdy rzeczywista wartość się zmieni. Myślę, że jest to świetne rozwiązanie, ponieważ pozwala uniknąć podklasy lub dodawania nowych właściwości.//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 } }
A oto w Swift:
func doToggle(switch: UISwitch) { if switch.on && !switch.selected { switch.selected = true // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE } else { switch.selected = false } }
źródło
Jeśli używasz tak wielu przełączników w swojej aplikacji, to jest problem ze zmianą kodu we wszystkich miejscach, w których jest zdefiniowana metoda działania UISwitch. Możesz ustawić niestandardowy przełącznik i obsłużyć zdarzenia tylko w przypadku zmiany wartości.
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
Ignorujemy zdarzenia, jeśli wartość jest taka sama jak zmieniona wartość. Umieść CustomSwitch we wszystkich klasach UISwitch w scenorysie, co rozwiąże problem i wywoła cel tylko raz, gdy wartość ulegnie zmianie
źródło
Mam wielu użytkowników, którzy mają ten sam problem, więc może to jest błąd,
UISwitch
więc właśnie znalazłem tymczasowe rozwiązanie tego problemu. Znalazłem jedengitHub
zwyczajKLSwitch
użycie tego na razie, mam nadzieję, że Apple naprawi to w następnej aktualizacji xCode: -https://github.com/KieranLafferty/KLSwitch
źródło
Jeśli nie musisz natychmiast reagować na zmianę wartości przełącznika, rozwiązaniem może być następujące rozwiązanie:
- (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]; } }
źródło
Ten problem nadal występuje od wersji beta iOS 9.3. Jeśli nie masz nic przeciwko temu, że użytkownik nie może przeciągać poza przełącznik, uważam, że
.TouchUpInside
raczej używa , niż.ValueChanged
działa niezawodnie.źródło
Nadal mam ten sam problem w iOS 9.2
Znalazłem rozwiązanie i udawałem, że może to pomóc innym
Utwórz zmienną count, aby śledzić, ile razy metoda została wywołana
int switchMethodCallCount = 0;
Zapisz wartość bool dla wartości przełącznika
bool isSwitchOn = No;
W metodzie zmiany wartości Switcha wykonaj pożądane działanie tylko dla pierwszego wywołania metody. Po ponownej zmianie wartości ustaw wartość licznika it wartość zmiennej bool na domyślną
- (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]; } } }
źródło
Ten problem nęka mnie, gdy przełączam przełącznik do innych zachowań. Generalnie rzeczy nie lubią przechodzić od
on
doon
. Oto moje proste rozwiązanie:@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 }
Pamiętaj tylko, aby ustawić również przy
self.lastSwitchState
każdej ręcznej zmianiemySwitch.on
! :)źródło
Ten typ problemu jest często spowodowany zmianą wartości. Nie musisz naciskać przycisku, aby uruchomić funkcję. To nie jest wydarzenie dotykowe. Za każdym razem, gdy programowo zmieniasz przełącznik na on / off, wartość zmienia się i ponownie wywołuje funkcję IBAction.
@RoNiT miał właściwą odpowiedź:
Szybki
func doToggle(switch: UISwitch) { if switch.on && !switch.selected { switch.selected = true // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE } else { switch.selected = false } }
źródło
DispatchQueue.main.async { self.mySwitch.setOn(false, animated: true) }
Działa to dobrze i nie wywołuje ponownie funkcji selektora.
źródło
To zadziałało dla mnie.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){ self.switch.isOn = true }
źródło