これは些細なことのように聞こえますが、私はいくつかの奇妙さに気づいています。 UISwitchのValueChangedイベントのハンドラーを配線しました。 expectは、ハンドラーが呼び出されるたびにスイッチの値が変わるということです。しかし、実際にはそうではありません常にその場合。スイッチをすばやくオン/オフすると、ハンドラーはスイッチの同じ状態で連続して呼び出される可能性があります(私の特定のアプリケーションではこれが問題です)。ですから、他の誰かがこの振る舞いに気づき、良い解決策を見つけたのではないかと思います。
-(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;
}
ハンドラーでスイッチの状態を取得します。
- (void)valueChanged:(UISwitch *)theSwitch {
BOOL flag = theSwitch.on;
}
押すたびにスイッチのオン/オフがすぐに切り替わることはありません。スイッチがオフの位置にある場合は、オンの位置にアニメートする前に数回押すことができます。アニメーションが完了するまで「オン」とは見なされないため、これらの各プレスは「スイッチをオンにする」と解釈されます。値が実際にはまだ変更されていないにもかかわらず、プレスごとに「valueChanged」コールバックを受け取ります。
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
これが私のために働く解決策です。また、スイッチが変更されると、プロパティの「変更予定/変更済み」通知を送信します。イベントは、前後の値が正しく維持されるという点でも正しく機能します。
@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
私の問題はばかげたものでした...私はenabled
値が変わることを期待していましたが、明らかにそれはスイッチの切り替え時に検査する正しい値ではありません。on
またはisOn
が正しい使用方法です。
最後の状態をログに記録して、状態が変更されたか、同じ状態でトリガーされたかを確認します。
スイッチをオフ/オンに切り替えると、「値が変更されました」が呼び出されます。したがって、valueChangedのメソッドを呼び出すことで、スイッチの変更を検出できます。