以前一直是纯代码编写开发APP,最近开始在项目里使用xib和storyboard,摸索了一整天,终于算基本掌握,但临近下班时,发现了一个很奇葩的问题…

问题场景是这样的:

用户修改绑定手机号时,需要获取验证码,然后按钮显示60秒倒计时,在此期间按钮点击失效,并每隔一秒通过setTile:forState方法更新按钮标题,显示倒计时。

最初的代码

1
2
NSString *title = [NSString stringWithFormat:@"%ld秒后重试", self.count];
[self.getCheckCodeButton setTitle:title forState:UIControlStateDisabled];

这应该是一个大家非常熟悉的一个常规需求,在以前使用纯代码编写时,不会有任何问题,然而今天的奇葩显现是,每次调用setTitle更新按钮标题时,都会消失一下再显示,看起来就是每个一秒的闪烁显示,特别酷炫(哈哈哈!),然而这并不是此刻我们需要的效果…

怎么办呢?

悄悄地去度娘一搜,还真有不少小伙伴也碰到了同样的问题,先来说说网上搜到的方法:

方法一:

在storyboard找到这个不老实的button,将他的type设置为Custom,默认是System。

默认值System.png

修改之后如下图:

改成Custom.png

很不幸的是,这种最简单的操作方式,在我这里 并没有奏效并没有奏效并没有奏效 !!!!!!
幸好网络资源棒棒哒,很快我又找到了另一种方法。

方法二:

这个方法虽然奏效,但我觉得很奇葩,很扯蛋,哈哈,可能奇葩的问题需要奇葩的方法,想出这个方法的同学其实还是很腻害的,膜拜!哈哈!!!
下面来看这位同学的方法:

1
2
3
NSString *title = [NSString stringWithFormat:@"%ld秒后重试", self.count];
self.getCheckCodeButton.titleLabel.text = title; // 这一句很重要,是关键,而且必须在setTitle之前,别问我为什么,我不知道,捂脸 捂脸 捂脸
[self.getCheckCodeButton setTitle:title forState:UIControlStateDisabled];

如注释所示,就是在setTitle之前,直接通过titleLabel给按钮标题赋值,然后再setTitle,这两行代买一个字都不能少,而且不需是这个顺序,setTitle断后。

这个方法虽然能解决问题,但对于有代码洁癖的人,怎么能接受这么奇葩的使用方式???
于是通过高人指点,最终的完美解决方案诞生了…看方法三

方法三:

先来看优雅的代码

1
2
3
4
5
NSString *title = [NSString stringWithFormat:@"%ld秒后重试", self.count];
[UIView performWithoutAnimation:^{
[self.getCheckCodeButton setTitle:title forState:UIControlStateDisabled];
[self.getCheckCodeButton layoutIfNeeded];
}];

现在我们先来谈谈出现闪烁问题的根本原因,通过xib创建的button,在setTitle的时候,默认添加了一个隐式的fade动画,使得title的更新是一个渐变的过程,而这个动画时间慢到了我们肉眼完全可以的感知的速度,于是出现了我们看到的闪烁,所以解决问题的关键,当然就是去禁用这个该死的动画了,而UIView的API里就已经提供了我们禁用隐式动画的block方法了,到此,问题完美解决!!!!

多些高人指点,觉得有记录和分享价值,睡前坚持把字码起来,希望小伙伴们喜欢!!!