93

编辑

它现在已在
上修复。不要进行任何调整来修复它。

编辑2

显然同样的问题在 iOS 8.0 和 8.1 中再次发生

编辑3

它现在已在
上修复。不要进行任何调整来修复它。


嗨,今天我在UISwitch's事件ValueChanged:调用中看到,continuously 当我更改为OnOff打开时Off,我的手指仍然在右侧和左侧移动。我使用 NSLog 制作了更清晰的 GIF 图像。

在此处输入图像描述

我的值更改方法是:

- (IBAction)changeSwitch:(id)sender{

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

iOS6 的 Switch 代码与我们预期的一样:

在此处输入图像描述

所以任何人都可以建议我只在其状态打开或关闭时调用一次。或者这是一个错误还是什么..?

更新

这是我的演示:

程序化添加 UISwitch

从 XIB 添加 UISwitch

4

12 回答 12

45

请看以下代码:

-(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");
    }
}
于 2013-10-28T07:38:52.347 回答
12

这里有同样的错误。我想我找到了一个简单的解决方法。我们只需要使用一个新BOOL的来存储之前的状态UISwitch和一个 if 语句在我们的IBAction(Value Changedfired) 中来检查 switch 的值是否真的改变了。

previousValue = FALSE;

[...]

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

不再有奇怪的行为。希望能帮助到你。

于 2014-01-17T23:15:03.893 回答
12

您可以使用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
    }
}
于 2015-11-06T08:21:15.263 回答
9

如果您在应用程序中使用了这么多开关,那么在定义 UISwitch 的 t 操作方法的所有位置更改代码都会出现问题。您可以进行自定义开关并仅在值更改时处理事件。

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 的所有类中。这将解决问题并在值更改时仅调用一次目标

于 2014-03-23T22:05:54.187 回答
7

我有很多用户面临同样的问题,所以这可能是UISwitch我现在发现的错误,以便临时解决它。我现在发现了一个gitHub自定义KLSwitch使用这个,希望苹果能在下一次 xCode 更新中解决这个问题:-

https://github.com/KieranLafferty/KLSwitch

于 2013-10-28T06:47:40.950 回答
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];
  }
}
于 2013-11-20T17:21:49.787 回答
3

从 iOS 9.3 测试版开始,这个问题仍然存在。如果您不介意用户无法将其拖出开关,我发现使用.TouchUpInside而不是.ValueChanged可靠地工作。

于 2016-02-19T18:54:47.817 回答
2

我在 iOS 9.2 中仍然面临同样的问题

我得到了解决方案并冒充,因为它可能会帮助其他人

  1. 创建计数变量以跟踪方法被调用的次数

    int switchMethodCallCount = 0;
    
  2. 保存开关值的布尔值

    bool isSwitchOn = No;
    
  3. 在 Switch 的值更改方法中,仅对第一个方法调用执行期望操作。当开关值再次更改设置计数值和布尔变量值为默认值时

    - (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];
    
    
        }
    }
    
    
    }
    
于 2016-01-19T13:55:15.543 回答
2

当我将开关与其他行为联系起来时,这个问题困扰着我。一般来说,事情不喜欢从onon。这是我的简单解决方案:

@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!:)

于 2016-04-21T21:55:39.840 回答
1

这类问题通常是由 ValueChanged 引起的。您无需按下按钮即可使功能运行。这不是触摸事件。每次您以编程方式将开关更改为开/关时,值都会更改并且它会再次调用 IBAction 函数。

@RoNiT 的正确答案是:

迅速

func doToggle(switch: UISwitch) {
    if switch.on && !switch.selected {
        switch.selected = true
        // SWITCH ACTUALLY CHANGED -- DO SOMETHING HERE
    } else {
        switch.selected = false
    }
}
于 2017-01-14T13:11:55.967 回答
0

这对我有用。

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()){
    self.switch.isOn = true
}
于 2019-03-04T10:25:47.150 回答
0
DispatchQueue.main.async {
        self.mySwitch.setOn(false, animated: true)
    }

这工作正常,不会再次调用选择器函数。

于 2018-05-15T16:31:31.427 回答