两种DispatchTime计算方式有何差异?AlamofireImage旧版代码疑问
AlamofireImage短延迟写法的疑问解析
先看旧版AlamofireImage里这段代码:
let tinyDelay = DispatchTime.now() + Double(Int64(0.001 * Float(NSEC_PER_SEC))) / Double(NSEC_PER_SEC) // Need to let the runloop cycle for the placeholder image to take affect DispatchQueue.main.asyncAfter(deadline: tinyDelay) { self.run(imageTransition, with: image) completion?(response) }
很多人会疑惑:为什么不直接写成更简洁的形式?
let tinyDelay = DispatchTime.now() + Double(0.001)
核心原因:避免浮点数精度损失,保证延迟时间精确
DispatchTime底层是用纳秒级整数来存储时间的,1秒对应NSEC_PER_SEC(即10^9纳秒)。
- 直接用
+ 0.001的话,0.001这个十进制小数无法被二进制浮点数精确表示,转换成纳秒整数时会出现微小偏差,实际延迟可能不是刚好0.001秒。 - 旧代码的写法,是先通过
0.001 * Float(NSEC_PER_SEC)算出0.001秒对应的纳秒数(1000000),转成Int64确保是精确整数,再转回Double做加法。这么做能强制延迟时间是精确的1000000纳秒,完全符合预期的0.001秒。
结合业务逻辑的必要性
注释里提到“需要让runloop循环一次,让占位图生效”,主线程的runloop处理UI更新是按循环周期来的。精确的0.001秒延迟刚好能让runloop完成一次循环,确保占位图的UI渲染已经完成,之后再执行图片过渡动画,不会出现占位图还没显示就开始动画的视觉bug。
内容的提问来源于stack exchange,提问作者Ahmet Sancar
相关产品推荐
相关产品推荐

