Это звучит тривиально, но я замечаю какую-то странность. Я подключил обработчик события Value Changed для UISwitch. Я бы ожидал, что каждый раз, когда обработчик называется значением переключателя, он изменится. Но на самом деле это не всегда так. Если вы быстро нажимаете на переключатель, обработчик может получить вызов последовательно с состоянием SAME для коммутатора (в моем конкретном приложении это проблема). Поэтому мне интересно, заметил ли кто-нибудь еще это поведение и нашел хорошее решение.
Обнаружение изменений в UISwitch
Ответ 1
-(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;
}
Ответ 2
Получить состояние переключателя в обработчике:
- (void)valueChanged:(UISwitch *)theSwitch {
BOOL flag = theSwitch.on;
}
Ответ 3
Каждое нажатие, которое вы делаете, не переключает переключатель вкл./выкл. Если переключатель находится в выключенном положении, вы можете получить пару нажатий, прежде чем он оживет в положение включения. Каждое из этих прессов интерпретируется как "включить переключатель", так как он не считается "on", пока анимация не завершится. Вы получаете обратный вызов "valueChanged" для каждого нажатия, несмотря на то, что значение еще не изменилось.
Ответ 4
Вот решение, которое работает для меня. Он также отправляет уведомление об изменении "будет/изменено" при изменении переключателя. Событие также функционирует правильно, так как значения до и после сохраняются правильно.
@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
Ответ 5
В iOS 11 была введена новая ошибка UISwitch, поэтому я не рекомендую подписываться на значения измененных событий. В противном случае ваш обратный вызов будет запускаться каждый раз, когда атрибут UISwitch
isOn
программно изменяется.
Вместо этого:
1) Подпишитесь на контакт внутри события:
let switch = UISwitch()
switch.addTarget(self, action: #selector(onSwitchValueChanged), for: .touchUpInside)
2) Внедрить метод обратного вызова:
func onSwitchValueChanged(_ switch: UISwitch) {
}
3) И теперь, когда вы программно меняете значение isOn
, оно не будет запускать метод onSwitchValueChanged
.
switch.isOn = !switch.isOn // 'onSwitchValueChanged' is not triggered
Ответ 6
Запишите последнее состояние, чтобы вы могли узнать, было ли изменено его состояние или было вызвано с тем же состоянием.
Ответ 7
При переключении выключения/включения вызывается "значение изменено". Таким образом, вы можете обнаружить изменение в переключателе, вызвав метод на valueChanged.
Ответ 8
Моя проблема была глупой... Я ожидал, что значение enabled
изменится, но, очевидно, это неверное значение для проверки переключателя коммутатора, on
или isOn
правильная вещь для использования.