×
广告

使用UISwitch重复调用UIControlEventValueChanged的问题解决方法

96
vinnyxiong
2016.03.29 09:25* 字数 481

1.UISwitch的问题

UISwitch通常这样使用:

UISwitch *showPhoneNumSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(80.f, 10.f, 100.f, 40.f)];
[showPhoneNumSwitch setOn:YES];
[showPhoneNumSwitch addTarget:self action:@selector(handleShowPhoneNumSwitch:) forControlEvents:UIControlEventValueChanged];

监听UIControlEventValueChanged事件,当UISwitch的值改变时就会调用handleShowPhoneNumSwitch:方法,如下:

- (void) handleShowPhoneNumSwitch:(id)sender
{
    UISwitch *switchButton = (UISwitch*)sender;
    BOOL isOn = [switchButton isOn];
    NSLog(@"当前值是:%@", isOn ? @"YES" : @"NO");
}

问题来了,如果手指在UISwitch控件上滑动,划出控件区域之后,手指不抬起,手指继续在屏幕上滑动,可以看到控制台一直在重复打印当前的状态,
如果我们直接在这个方法里面处理一些事务,比如提交网络请求,那么这些事务将重复执行完全一致的逻辑,消耗无谓的资源,甚至可能出现逻辑错误,比如下面这种逻辑:

- (void) handleShowPhoneNumSwitch:(id)sender
{
    UISwitch *switchButton = (UISwitch*)sender;
    BOOL isOn = [switchButton isOn];
    NSLog(@"当前值是:%@", isOn ? @"YES" : @"NO");
    _isShowPhoneNum = isOn;
    [[ServiceFactory service] requestModifyPhoneNumPrivacyConfig
        :self.teamUin showPhoneNum: _isShowPhoneNum handler:^(uint32_t errorCode, id resp) {
        if (errorCode != 0) {
            [switchButton setOn:!_isShowPhoneNum animated:YES]; // 网络请求返回错误,这里给 UISwitch 设置了相反的值
        }
    }];
}

如上这种逻辑,在网络请求错误的时候,会把UISwitch的值设置为相反的值,如果这时候手指继续滑动,那么又会触发UIControlEventValueChanged进来这个方法,网络错误的地方又会设置相反的值,这样两种值交替出现。最终的效果可能是并非我们想要的效果。

2.解决方案:

其实在手指滑动的时候,UISwitch的值并未发生改变,只是重复触发UIControlEventValueChanged,可以在方法内先进行一个判断,如果当前值跟上一次的值一样,那么就不需要执行方法里面的逻辑。
代码修正如下:

- (void) handleShowPhoneNumSwitch:(id)sender
{
    UISwitch *switchButton = (UISwitch*)sender;
    BOOL isOn = [switchButton isOn];
    if (isOn != _isShowPhoneNum) {  // 判断是否与上次进来相同
        _isShowPhoneNum = isOn;
        [[ServiceFactory service] requestModifyPhoneNumPrivacyConfig
            :self.teamUin showPhoneNum: _isShowPhoneNum handler:^(uint32_t errorCode, id resp) {
            if (errorCode != 0) {
               _isShowPhoneNum = !isOn;
               [switchButton setOn:_isShowPhoneNum animated:YES];
            }
        }];
    }
}

其中_isShowPhoneNum可以作为成员变量,先初始化为UISwitch的初始值,当_isShowPhoneNum与当前值相同时,不需要执行里面的逻辑。

吐槽:这个控件如果手指滑动之后没有抬起继续滑动,就会不断地触发UIControlEventValueChanged,怎么看都不合理。

本文首发于我的个人博客,欢迎访问:使用UISwitch重复调用UIControlEventValueChanged的问题解决方法

Web note ad 1