[ACCEPTED]-Detecting a change in UISwitch-uiswitch

Accepted answer
Score: 19
   -(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

Score: 9

In iOS 11 a new UISwitch bug was introduced so I don't recommend 3 subscribing to value changed events. Otherwise 2 your callback will be triggered every time 1 UISwitch's isOn attribute changes programmatically.

Instead:

  1. Subscribe for touch up inside event:
let switch = UISwitch()
switch.addTarget(self, action: #selector(onSwitchValueChanged), for: .valueChanged)
  1. Implement the callback method:
func onSwitchValueChanged(_ switch: UISwitch) {
        
}
  1. And now when you programmatically change isOn value, it won't trigger onSwitchValueChanged method.

switch.isOn = !switch.isOn // 'onSwitchValueChanged' is not triggered

Score: 8

Get state of switch in handler:

- (void)valueChanged:(UISwitch *)theSwitch {
   BOOL flag = theSwitch.on;
}

0

Score: 7

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

Score: 1

Here's a solution that works for me. It 4 also sends a property "will/did change" notification 3 when the switch is changed. The event also 2 functions correctly in that the before and 1 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
Score: 0

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

Score: 0

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

Score: 0

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

More Related questions