Detecting a change in UISwitch

0 votes
asked Nov 4, 2010 by john

This sounds trivial but I'm noticing some weirdness. I've wired up a handler for the Value Changed event of a UISwitch. What I would expect is that each time the handler is called the value of the switch would change. But that's actually not always the case. If you press the switch rapidly on/off the handler can get called consecutively with the SAME state for the switch (in my specific application this is an issue). So I'm wondering if anyone else has noticed this behavior and has figured out a good solution.

7 Answers

0 votes
answered Nov 4, 2010 by ben

Log the last state so you can tell if its changed state or has been triggered with the same state.

0 votes
answered Nov 4, 2010 by erdemus

Get state of switch in handler:

- (void)valueChanged:(UISwitch *)theSwitch {
   BOOL flag = theSwitch.on;
}
0 votes
answered Nov 10, 2011 by antsyawn

Each press you make doesn't immediately toggle the switch on/off. If the switch is in the off position, you can get a couple of presses in before it animates to the on position. Each of these presses are interpreted as "turn the switch on", since it is not considered "on" until the animation has completed. You get a "valueChanged" callback for each press despite the fact that the value hasn't actually changed yet.

0 votes
answered Nov 21, 2012 by nids

When you toggle the switch off/On the "value changed" has been called.So you can detecting a change in switch by calling method on valueChanged.

0 votes
answered Nov 17, 2013 by user1105951
   -(void) createSwitch
    {
        self.searchExistSearchNewSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0,0,0,0)];
        [self.searchExistSearchNewSwitch addTarget:self action:@selector(switchValueChanged:) forControlEvents:UIControlEventValueChanged];
        [self.view addSubview:self.searchExistSearchNewSwitch];
    }
    - (void)switchValueChanged:(UISwitch *)theSwitch
    {
        BOOL flag = theSwitch.isOn;
    }
0 votes
answered Nov 15, 2014 by leslie-godwin

Here's a solution that works for me. It also sends a property "will/did change" notification when the switch is changed. The event also functions correctly in that the before and after values are maintained correctly.

@interface MySwitch : UISwitch

@end

@implementation MySwitch
{
    BOOL _previousValue;
    BOOL _returnPreviousValue;
}

- (instancetype) initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder: aDecoder];
    if (!self) return nil;

    _previousValue = self.isOn;
    [self addTarget: self action: @selector(_didChange)
                forControlEvents: UIControlEventValueChanged];

    return self;
}

- (instancetype) initWithFrame: (CGRect) frame
{
    self = [super initWithFrame: frame];
    if (!self) return nil;

    [self addTarget: self action: @selector(_didChange)
                forControlEvents: UIControlEventValueChanged];

    return self;
}

- (BOOL) isOn
{
    return (_returnPreviousValue)
                        ? _previousValue
                        : [super isOn];
}

- (void) setOn:(BOOL) on animated: (BOOL) animated
{
    [super setOn: on animated: animated];

    _previousValue = on;
}

- (void) _didChange
{
    BOOL isOn = self.isOn;

    if (isOn == _previousValue) return;

    _returnPreviousValue = true;
    [self willChangeValueForKey: @"on"];
    _returnPreviousValue = false;

    _previousValue = isOn;
    [self didChangeValueForKey:  @"on"];
}

@end
0 votes
answered Sep 15, 2017 by mike

My problem was a stupid one... I was expecting the enabled value to change, but obviously that isn't the correct value to inspect upon the toggle of the switch, the on or isOn is the correct thing to use.

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...