iPhone/iPad 中的 NSTimer 和加速度计
我的应用程序有一个要求,如果应用程序/ipad 上大约 3 小时没有发生任何活动,则需要向用户显示一些消息。 我考虑了一个在启动时启动 NSTimer 的解决方案。如果用户执行任何操作,我就会使计时器无效并启动一个新计时器。然而,该应用程序上有视频播放功能,据我所知,用户可能会观看视频大约 3 个小时,并且在此期间没有执行任何其他操作,但仍然会收到消息。
因此,另一种方法是每次检测到 ipad/iphone 移动时使计时器无效并启动计时器。换句话说,使用加速度计并在回调中检测加速度,我可以使计时器无效并再次创建计时器。 但我对这种方法的担忧是,即使对于最小的动作,计时器也必须失效并重新创建。这种方法会以任何方式影响性能吗?
谢谢和问候, 赫塔尔
I have a requirement in my app which requires me to display some message to the user if there is no activity happening for about 3 hours on the app/ipad.
I considered the solution of having an NSTimer that would start at launch. If the user performs any action, I invalidate the timer and start a new one. However, there is video playback on the app and for all I know, the user may be watching the video for about 3 hours and performs no other action during that time and would still get the message.
So, an alternative is to invalidate and start the timer every time I detect the ipad/iphone has moved. In other words, use the accelerometer and in the call back to detect acceleration, I can invalidate and create the timer again.
But my worry with this approach is that even for smallest of movements, the timer would have to be invalidated and recreated. Will this approach in any way impact performance?
Thanks and Regards,
hetal
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
创建一个计时器并不那么昂贵,但还是有点贵。
好消息是您可以任意更改触发日期:
或者,对于稍微更少的开销:(
我认为 CFAbsoluteTimeGetCurrent() 开销大于对象创建开销,但是,嗯。
)稍微更好的解决方案可能是大部分时间都不使用计时器;只需更新“上次活动”时间戳即可。当计时器触发时,查看“上次活动”时间戳。如果超过 3 小时前,则显示通知。如果距离不到3小时,则适当设置下一次点火日期;这意味着计时器(平均)最多每 1.5 小时触发一次,这可能不如反复更改触发日期那么昂贵。
请参阅
mach_absolute_time()
了解相对较低开销的时基(预先计算 3 小时以 mach_absolute_time 为单位)。它仍然需要大约 3 微秒,这实际上是永远的(1000 个时钟周期!)。如果您真的担心开销,只需在每次发生事情时设置一个“活动”标志,并使用(例如)1 小时计时器。当计时器触发时,执行类似
if (activity) {counter = 0; 的操作活动= 0; } else { 计数器 ++; if (counter == 3) { ... } }
。这里和那里的几微秒是否比每小时触发一次的计时器成本更高,这是有争议的,但它们都是可以忽略不计的。更大的问题是加速计消耗电力和 CPU 时间(并且提供更新需要 CPU 时间)。设置 updateInterval = 10 左右会减少开销,并且操作系统将其限制为一个合理的值(大约 1 秒)。
Creating a timer is not that expensive, but it's still a little expensive.
The good news is that you can arbitrarily change the fire date:
Alternatively, for very slightly less overhead:
(I think the CFAbsoluteTimeGetCurrent() overhead is more than the object-creation overhead, but meh.)
A slightly better solution might be to leave the timer alone most of the time; simply update the "last activity" timestamp. When the timer fires, look at the "last activity" timestamp. If it's more than 3 hours ago, thenshow the notification. If it's less than 3 hours ago, then set the next fire date appropriately; this means the timer fires (on average) at most every 1.5 hours, which is probably not as costly as repeatedly changing the fire-date.
See
mach_absolute_time()
for a relatively low-overhead timebase (pre-calculating what 3 hours is in mach_absolute_time units). It still takes about 3 microseconds, which is practically forever (1000 clocks cycles!).If you're really worried about overhead, simply set an "activity" flag every time something happens, and use (e.g.) a 1 hour timer. When the timer fires, do something like
if (activity) {counter = 0; activity = 0; } else { counter ++; if (counter == 3) { ... } }
. It's debatable whether a couple of microseconds here and there are more costly than a timer firing every hour, but they're both pretty negligible.The far bigger problem is that the accelerometer eats power and CPU time (and delivering updates takes CPU time). Setting
updateInterval = 10
or so will reduce the overhead, and it's capped to a sensible value (around 1 s) by the OS.Apple 在多任务处理中有一个功能,他们称之为“任务完成”,由
使用 - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler
找到此处以及更多内容此处Apple has a feature in multitasking that they call "Task finishing" use by
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler
Found here and more stuff here难道您不能在视频开始时向您的
NSTimer
发送消息以使计时器无效吗?然后当电影结束时,重新启动计时器。Can't you just send a message to your
NSTimer
whenever a video starts, to invalidate the timer? Then when the movie ends, start the timer back up.