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; [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
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