问题描述
自定义了一个AlertView控件,更新数据过程中,显示取消按钮,数据更新完成以后,移除取消按钮,显示完成按钮,在更新数据时,点击取消按钮,在数据更新完成时,按钮才响应。我们的需求就是用户可以取消,但是按钮无响应,导致这个功能无法实现。
思考过程
首先想到的是UI线程被阻塞了,但是我做了错误的测试,只是将显示alertview的代码放到了主线程,这并不是测试主线程的代码,起不到效果;
其次,我想到取消按钮的action是不是没添加成功,检查发现添加成功了;
然后,我尝试使用其他的alertview控件去实现同样的展示效果,但是取消按钮在更新过程中依然无法响应。
再然后,我写了一段测试代码,在子线程中sleep 3s模拟更新过程,之后在主线程更新按钮状态,此时,我发现取消按钮能正常响应。此时问题定位已经定位了80%。我继续查看更新数据的方法,一步步的往深处看执行的方法,发现有一处代码执行时间特别长,但是确在主线程中执行,此刻我恍然大悟,原来更新操作阻塞了主线程,才导致了UIButton无法响应啊!
问题原因
主线程中有耗时操作,block嵌套block,方法体是在子线程中执行,但是block中的代码却是在主线程中;这个问题不容易发现。
block1 ^{
子线程{
耗时任务;
主线程{
耗时任务;
}
}
}
问题衍生
遇到按钮无法响应的问题,首先想想是否主线程被阻塞;
解决方法
将主线程中执行的耗时任务放到子线程中;
block1 ^{
子线程{
耗时任务;
主线程{
子线程{
耗时任务;
}
}
}
}
总结
虽然主线程被阻塞了,但是UIImageView的rotateAnimation依然能动画,说明BaseAnimation的执行是在子线程中执行的。