iOS面试:以+ scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?

在 iOS 开发中,使用 +scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: 创建的定时器(NSTimer)在滑动页面上的列表时可能会出现回调暂停的现象。这主要是因为定时器的运行依赖于 RunLoop 的模式,而在滑动列表时,RunLoop 会进入一个特殊的模式(如 UITrackingRunLoopMode),这会导致定时器的回调被暂停。

原因分析

RunLoop 模式

当用户在滑动列表时,RunLoop 会切换到 UITrackingRunLoopMode 模式。在这个模式下,只有与用户交互相关的事件会被处理,定时器通常会被暂停,因为它们是在 NSDefaultRunLoopMode 中运行的。

定时器的添加模式

使用 +scheduledTimerWithTimeInterval: 方法创建的定时器默认添加到 NSDefaultRunLoopMode,这意味着当 RunLoop 切换到 UITrackingRunLoopMode 时,定时器的回调不会被触发。

解决方案

要解决这个问题,可以将定时器添加到 NSRunLoopCommonModes 模式,这样它就可以在多个模式下运行,包括滑动时的 UITrackingRunLoopMode。下面是如何实现这一点的示例代码:

// 创建并添加定时器到 NSRunLoopCommonModes  NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(handleTimer) userInfo:nil repeats:YES];  

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];  

其他注意事项

手动管理定时器

如果你需要在不同的模式下手动管理定时器,可以在滑动开始和结束时手动添加或移除定时器。

使用 GCD 或 CADisplayLink

如果你发现 NSTimer 的行为不符合需求,可以考虑使用 Grand Central Dispatch (GCD) 或 CADisplayLinkCADisplayLink 是一个专门用于与屏幕刷新同步的定时器,适合处理动画和高频率的更新。

示例代码:使用 CADisplayLink

CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink)];  

[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];  

在滑动列表时,NSTimer 的回调暂停是由于 RunLoop 模式的切换导致的。通过将定时器添加到 NSRunLoopCommonModes,可以确保它在滑动时继续工作。此外,考虑使用 CADisplayLink 或 GCD 作为替代方案,以满足更高频率的更新需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值