简体   繁体   English

iPhone / iPad中的NSTimer和加速度计

[英]NSTimer and accelerometer in iPhone/iPad

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. 我的应用程序中有一项要求,如果在该应用程序/ ipad上大约3个小时内没有任何活动发生,则要求我向用户显示一些消息。 I considered the solution of having an NSTimer that would start at launch. 我考虑了在启动时启动NSTimer的解决方案。 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. 但是,该应用程序上有视频播放功能,据我所知,用户可能正在观看视频大约3个小时,并且在此期间未执行其他任何操作,并且仍然会收到消息。

So, an alternative is to invalidate and start the timer every time I detect the ipad/iphone has moved. 因此,另一种方法是,每当我检测到ipad / iphone移动时,使计时器无效并启动计时器。 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 感谢和问候,健康

苹果有一个特点,在多任务处理,他们称之为“任务完成”使用的- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^)(void))handler发现这里和更多的东西在这里

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: 好消息是您可以随意更改开火日期:

[timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:3*60*60]];

Alternatively, for very slightly less overhead: 另外,对于非常略少的开销:

CFRunLoopTimerSetNextFireDate((CFRunLoopTimerRef)timer, CFAbsoluteTimeGetCurrent()+3*60*60);

(I think the CFAbsoluteTimeGetCurrent() overhead is more than the object-creation overhead, but meh.) (我认为CFAbsoluteTimeGetCurrent()的开销比对象创建的开销大,但是。)

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. 如果已超过3小时,则显示通知。 If it's less than 3 hours ago, then set the next fire date appropriately; 如果还不到3个小时,请适当设置下一个开火日期。 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. 这意味着计时器(平均)最多每1.5小时触发一次,这可能不像重复更改触发日期那样昂贵。

See mach_absolute_time() for a relatively low-overhead timebase (pre-calculating what 3 hours is in mach_absolute_time units). 有关开销相对较低的时基,请参见mach_absolute_time() (以mach_absolute_time单位预先计算3小时​​)。 It still takes about 3 microseconds, which is practically forever (1000 clocks cycles!). 它仍然需要大约3微秒,这几乎是永远的时间(1000个时钟周期!)。

If you're really worried about overhead, simply set an "activity" flag every time something happens, and use (eg) a 1 hour timer. 如果您真的担心开销,只需在发生任何事情时设置一个“活动”标志,然后使用(例如)1小时计时器。 When the timer fires, do something like if (activity) {counter = 0; activity = 0; } else { counter ++; if (counter == 3) { ... } } 当计时器启动时,执行if (activity) {counter = 0; activity = 0; } else { counter ++; if (counter == 3) { ... } } if (activity) {counter = 0; activity = 0; } else { counter ++; if (counter == 3) { ... } } if (activity) {counter = 0; activity = 0; } else { counter ++; if (counter == 3) { ... } } . 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). 更大的问题是加速度计会消耗功率和CPU时间(而交付更新会占用CPU时间)。 Setting updateInterval = 10 or so will reduce the overhead, and it's capped to a sensible value (around 1 s) by the OS. 设置updateInterval = 10左右将减少开销,并且操作系统将其限制为合理的值(大约1 s)。

Can't you just send a message to your NSTimer whenever a video starts, to invalidate the timer? 每当视频开始播放时,您是否不能仅向NSTimer发送消息以使计时器无效? Then when the movie ends, start the timer back up. 电影结束后,请重新启动计时器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM