Click here to Skip to main content
Click here to Skip to main content

iOS Tricks: Giving UISwitch's "on" Property Will/Did Change Observable Notifications

, 15 Jul 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
The UISwitch's UIControlEventValueChanged event is pretty useless if you'd like to get a notification only when the switch value actually changes.

Introduction

The UISwitch's UIControlEventValueChanged event is pretty useless if you'd like to get a notification only when the switch value actually changes. I have a solution that allows you to attach to the switch's "on" property's to get accurate change notifications.

Background

UISwitch inherits from UIControl which only has a UIControlEventValueChangedbefore value for you to determine if the value actually did change.

The More Better Class

The MySwitch class tweaks the UISwitch control by posting key/value change events when the control's value changes. It stores the previous value so it can determine when the on property actually changes.

MySwitch Interface

@interface MySwitch : UISwitch
@end

MySwitch Implementation

@implementation MySwitch
{
    BOOL _previousValue;
    BOOL _returnPreviousValue;
}

- (instancetype) initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder: aDecoder];
    if (!self) return nil;
    
    _previousValue = self.isOn; // if constructed via a nib
    [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) // see [_didChange]
                        ? _previousValue
                        : [super isOn];
}

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

    _previousValue = on; // if set manually
}

- (void) _didChange
{
    BOOL isOn = self.isOn;
    
    if (isOn == _previousValue) return;
    
    _returnPreviousValue = true; // the will change might query 
                      // the current value. (isOn must then return the previous value) 
    [self willChangeValueForKey: @"on"];
    _returnPreviousValue = false;
    
    _previousValue = isOn;
    [self didChangeValueForKey:  @"on"];
}

@end

And Then Make Your Codez Sweet

All you need to do is add an observer to the MySwitch instance. The observer can even get the old and new values in the change parameter. (See NSKeyValueObservingOptionOld and NSKeyValueObservingOptionNew)

- (void) viewDidLoad
{
    [super viewDidLoad];

    [self.switchView addObserver: self forKeyPath: @"on" 
                         options: NSKeyValueObservingOptionNew context: nil];
}

- (void) observeValueForKeyPath: (NSString *) 
keyPath ofObject: (id) object change: (NSDictionary *) change context: (void *) context
{
    if ([[change objectForKey: @"new"] boolValue])
    {
        self.textView.text = 
            [self.textView.text stringByAppendingString: @"changed to: ON\n"];
    }
    else
    {
        self.textView.text = 
            [self.textView.text stringByAppendingString: @"changed to: OFF\n"];
    }
}

- (void) toggleSwitch : (id) sender
{
    self.switchView.on = !self.switchView.on;
}

History

  • Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Leslie Godwin
Technical Lead FNB Connect
South Africa South Africa
iOS Technical Lead at FNB
-

Computers are really sweet. Aren't they?
Yup they are...

I've always loved writing tools and components...never been very interested in playing games....always wanted to be able to write them though.

And, yes. I'm still pretty annoyed they discontinued the Amiga computer.
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 4 PinmemberKarstenK16-Jul-14 6:12 
GeneralRe: My vote of 4 PinmemberLeslie Godwin17-Jul-14 2:26 
GeneralMy vote of 5 Pinmemberquinn.harly15-Jul-14 11:51 
GeneralRe: My vote of 5 PinmemberLeslie Godwin15-Jul-14 23:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150414.1 | Last Updated 15 Jul 2014
Article Copyright 2014 by Leslie Godwin
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid