web-dev-qa-db-ja.com

UISwitchの変更を検出する

これは些細なことのように聞こえますが、私はいくつかの奇妙さに気づいています。 UISwitchのValueChangedイベントのハンドラーを配線しました。 expectは、ハンドラーが呼び出されるたびにスイッチの値が変わるということです。しかし、実際にはそうではありません常にその場合。スイッチをすばやくオン/オフすると、ハンドラーはスイッチの同じ状態で連続して呼び出される可能性があります(私の特定のアプリケーションではこれが問題です)。ですから、他の誰かがこの振る舞いに気づき、良い解決策を見つけたのではないかと思います。

22
John
   -(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;
    }
19
user1105951

ハンドラーでスイッチの状態を取得します。

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

押すたびにスイッチのオン/オフがすぐに切り替わることはありません。スイッチがオフの位置にある場合は、オンの位置にアニメートする前に数回押すことができます。アニメーションが完了するまで「オン」とは見なされないため、これらの各プレスは「スイッチをオンにする」と解釈されます。値が実際にはまだ変更されていないにもかかわらず、プレスごとに「valueChanged」コールバックを受け取ります。

7
antsyawn

IOS 11では 新しいUISwitchバグ が導入されたため、値が変更されたイベントをサブスクライブすることはお勧めしません。それ以外の場合、コールバックはUISwitchisOn属性がプログラムで変更されるたびにトリガーされます。

代わりに:

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

5
Vadim Bulavin

これが私のために働く解決策です。また、スイッチが変更されると、プロパティの「変更予定/変更済み」通知を送信します。イベントは、前後の値が正しく維持されるという点でも正しく機能します。

@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
1
Leslie Godwin

私の問題はばかげたものでした...私はenabled値が変わることを期待していましたが、明らかにそれはスイッチの切り替え時に検査する正しい値ではありません。onまたはisOnが正しい使用方法です。

0
Mike

最後の状態をログに記録して、状態が変更されたか、同じ状態でトリガーされたかを確認します。

0
Ben

スイッチをオフ/オンに切り替えると、「値が変更されました」が呼び出されます。したがって、valueChangedのメソッドを呼び出すことで、スイッチの変更を検出できます。

0
nids