Normal 和 Fast 的值

📅 2026/7/19 23:35:42
Normal 和 Fast 的值
UIScrollViewDecelerationRateNormal和UIScrollViewDecelerationRateFast的值打印如下:UIScrollViewDecelerationRateNormal(lldb) po import UIKit(lldb) p (UIScrollViewDecelerationRate)UIScrollViewDecelerationRateNormal(UIScrollViewDecelerationRate) 0.998UIScrollViewDecelerationRateFast(lldb) p (UIScrollViewDecelerationRate)UIScrollViewDecelerationRateFast(UIScrollViewDecelerationRate) 0.98999999999999999decelerationRate的数值越小减速越快。UIScrollViewDecelerationRateFast就是浮点数0.99。由于计算机对浮点数表示精度问题显示为0.98999999999999999。2 decelerationRate setter 的实现decelerationRate的设置函数代码比较短直接贴出来:UIKitCore-[UIScrollView setDecelerationRate:]:- 0x1a2a4998c 0: adrp x8, 5091// 1. 读取阈值到 d10x1a2a49990 4: ldr d1, [x8, #0x558]// 2. 将要设置的值与阈值比较0x1a2a49994 8: fcmp d0, d1// 3. 如果要设置的值 阈值w8 置为 1否则w8 置为 00x1a2a49998 12: cset w8, lt0x1a2a4999c 16: adrp x9, 5091// 4. x9 存储 UIScrollViewDecelerationRateNormal 和 UIScrollViewDecelerationRateFast 组成的数组首地址0x1a2a499a0 20: add x9, x9, #0x5a0 ; UIScrollTestParametersLengthAutomatic 128// 5. 将 UIScrollViewDecelerationRateNormal 或者 UIScrollViewDecelerationRateFast 读取到 d00x1a2a499a4 24: ldr d0, [x9, w8, uxtw #3]0x1a2a499a8 28: adrp x8, 4164650x1a2a499ac 32: ldrsw x8, [x8, #0xf9c]0x1a2a499b0 36: add x8, x0, x8// 6. 存储 decelerationRate 到 UIScrollView 对象0x1a2a499b4 40: stp d0, d0, [x8]0x1a2a499b8 44: ret注释1读取阈值到寄存器d1。代码后面会将要设置的值与阈值比较。打印阈值为:(lldb) p $d1(double) 0.99399999999999999可以看到阈值就是0.994。这个阈值正好是UIScrollViewDecelerationRateNormal和UIScrollViewDecelerationRateFast的中间值。同样由于计算机浮点数精度问题表示为0.99399999999999999。注释2注释3将要设置的值与阈值进行比较。如果要设置的值比阈值小那么寄存器w8被置为1否则w8被置为0。寄存器w8的值后面会看到成为数组索引。注释4将UIScrollViewDecelerationRateNormal和UIScrollViewDecelerationRateFast组成的数组首地址读入寄存器x9。可以打印这个数组的内容:(lldb) x/2fg $x90x1a3e2c5a0: 0.9980x1a3e2c5a8: 0.98999999999999999从打印内容可以看到数组第一项是UIScrollViewDecelerationRateNormal数组第二项是UIScrollViewDecelerationRateFast。注释5根据寄存器w8做索引读入相应的值到寄存器d0。如果要设置的值比阈值大那么就读入UIScrollViewDecelerationRateNormal否则读入UIScrollViewDecelerationRateFast。注释6将最终的值存入到UIScrollView对象中。存储decelerationRate的实例变量相对于UIScrollView首地址偏移量存储在寄存器x8打印为:(lldb) p/x $x8(unsigned long) 0x0000000000000358通过_ivarDescription方法打印UIScrollView的所有实例变量经过尝试可以发现偏移量0x358处的实例变量为_decelerationFactor:(lldb) po class_getInstanceVariable(UIScrollView.class, “_decelerationFactor”)0x000000020a6adbd8(lldb) po ivar_getOffset(0x000000020a6adbd8)0x0000000000000358_decelerationFactor是一个结构体存储这水平和垂直减速比例值:_decelerationFactor (struct CGSize): {0.998, 0.998}总结一下如果设置UIScrollView的decelerationRate属性系统会将设置的值与阈值0.994进行比较:如果设置的值大于阈值那么系统会选择UIScrollViewDecelerationRateNormal;如果设置的值小于阈值那么系统会选择UIScrollViewDecelerationRateFast。也就是说无论外界设置何种值系统只会在UIScrollViewDecelerationRateNormal和UIScrollViewDecelerationRateFast中进行选择。3 decelerationRate getter 的实现decelerationRate的getter方法也很短代码如下:UIKitCore-[UIScrollView decelerationRate]:0x1a3ba2354 0: adrp x8, 4120240x1a3ba2358 4: ldrsw x8, [x8, #0xf9c]// 1. 读取 _decelerationFactor 的水平值- 0x1a3ba235c 8: ldr d0, [x0, x8]0x1a3ba2360 12: ret注释1寄存器x8存储这_decelerationFactor结构体相对于UIScrollView首地址的偏移量:(lldb) p/x $x8(unsigned long) 0x0000000000000358这里将_decelerationFactor的水平值读取出来作为结果返回。4 _decelerationFactor 结构体如果我们直接设置UIScrollView的decelerationRate属性系统始终会把设置的值调整为预定义的UIScrollViewDecelerationRateNormal或者UIScrollViewDecelerationRateFast。那么我们能否直接设置_decelerationFactor结构体从而使用不同的减速系数呢通过调用_methodDescription查看UIScrollView的所有方法可以找到如下2个私有方法:(void) setHorizontalScrollDecelerationFactor:(double)arg1; (0x138bd7d00)(void) setVerticalScrollDecelerationFactor:(double)arg1; (0x138bd7d70)这两个方法这是设置_decelerationFactor结构体的水平值和垂直值。我们先看setHorizontalScrollDecelerationFactor:方法的实现垂直方法的实现类似:UIKitCore-[UIScrollView setHorizontalScrollDecelerationFactor:]:- 0x1a3ba2378 0: adrp x8, 4120240x1a3ba237c 4: ldrsw x8, [x8, #0xf9c]// 1. 将设置的值直接存入到 _decelerationFactor 结构体的水平分量0x1a3ba2380 8: str d0, [x0, x8]0x1a3ba2384 12: ret注释1将设置的值直接存入到_decelerationFactor结构体的水平分量。因此通过上面两个私有方法就可以设置decelerationRate的值为[0, 1)直接的值。注意不能通过上面2个私有方法将decelerationRate的值设置为1.0否则滚动时会发生崩溃。比如如果我们调用setVerticalScrollDecelerationFactor:方法将垂直减速系数设置为0.999999那么就会发现拖动UIScrollView之后的减速非常缓慢。