IOS7 UISwitch его событие ValueChanged: постоянно звонит это ошибка или что..?

Изменить

Теперь он исправлен на
Не пытайтесь исправить это.

Edit2

По-видимому, такая же проблема повторится и в iOS 8.0 и 8.1

Edit3

Теперь он исправлен на
Не пытайтесь исправить это.


Привет Сегодня я видел в UISwitch's Событие ValueChanged: Вызов continuously, пока я меняю на On на Off или Off на "Вкл", и мой палец перемещается по-прежнему с правой стороны, а также с левой стороны, Я закрепил GIF-изображение для более четкого представления в NSLog.

enter image description here

Мой измененный метод:

- (IBAction)changeSwitch:(id)sender{

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

}

iOS6 тот же самый код коммутатора работает как ожидалось:

enter image description here

так может ли кто-нибудь предложить мне, чтобы он вызывал только одно время его состояние вкл. или выкл. или это ошибка или что..?

UPDATE

Вот моя демонстрация:

программный Добавить UISwitch

из XIB, добавляющего UISwitch

Ответ 1

У меня появилось много пользователей, которые сталкиваются с одной проблемой, поэтому может быть, это ошибка UISwitch, поэтому я нашел ее только для временного решения. Я нашел один gitHub пользовательский KLSwitch использовать это, теперь надеюсь, что apple исправит это в следующем обновлении xCode: -

https://github.com/KieranLafferty/KLSwitch

Ответ 2

См. следующий код:

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

Ответ 3

Такая же ошибка здесь. Я думаю, что нашел простой способ обхода. Нам просто нужно использовать новый BOOL, который сохраняет предыдущее состояние UISwitch и оператор if в нашем IBAction (Value Changed), чтобы проверить, действительно ли значение переключателя было изменено.

previousValue = FALSE;

[...]

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

Нет более странного поведения. Надеюсь, что это поможет.

Ответ 4

Вы можете использовать свойство UISwitch .selected, чтобы убедиться, что ваш код выполняется только один раз при изменении фактического значения. Я думаю, что это отличное решение, поскольку оно позволяет избежать подкласса или добавления новых свойств.

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

И вот он в Swift:

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

Ответ 5

Если вы используете так много переключателей в своем приложении, тогда возникает проблема с изменением кода во всех местах, где t метод действия UISwitch определен. Вы можете создавать настраиваемый переключатель и обрабатывать события только в случае изменения значения.

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

Мы игнорируем события, если значение такое же, как измененное значение. Положите CustomSwitch во всех классах UISwitch в раскадровке. Это решит проблему и вызовет цель только один раз, когда значение изменится

Ответ 6

Если вам не нужно мгновенно реагировать на изменение значения переключателя, следующим может быть решение:

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

Ответ 7

Я все еще сталкиваюсь с той же проблемой в iOS 9.2

Я получил решение и позировал, поскольку это могло бы помочь другим

  • Создать счетную переменную для отслеживания количества раз, когда метод получил вызов

    int switchMethodCallCount = 0;
    
  • Сохранить значение bool для значения переключателя

    bool isSwitchOn = No;
    
  • В методе изменения значения переключателя выполняется действие желания только для первого вызова метода. Когда значение переключателя снова изменяет значение счетчика установки и значение переменной bool по умолчанию

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

Ответ 8

Эта проблема все еще здесь, как и бета-версия iOS 9.3. Если вы не возражаете против того, что пользователь не может перетащить за пределы коммутатора, я считаю, что использование .TouchUpInside, а не .ValueChanged работает надежно.

Ответ 9

Эта проблема поражает меня, когда я привязываю переключатель к другому поведению. Обычно вещи не любят идти от on до on. Здесь мое простое решение:

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

Просто не забудьте также установить self.lastSwitchState каждый раз, когда вы вручную меняете mySwitch.on!:)

Ответ 10

Этот тип проблемы часто вызван ValueChanged. Вам не нужно нажимать кнопку, чтобы вызвать запуск функции. Это не событие касания. Каждый раз, когда вы программно меняете переключатель на включение/выключение, значение изменяется, и он снова вызывает функцию IBAction.

@RoNiT имел правильный ответ:

Swift

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