我有一个后台应用程序,需要每1.5秒向另一个进程发送一个keep-alive。在OSX 10.7和10.8中一切都运行顺畅,但在OSX 10.9下,许多保持活动通知都会丢失,有时会达到3次。通常一切正常,前3或4分钟就会出现问题。
经过进一步检查后,似乎OSX Mavericks“定时器合并”功能将负责决定将请求的1.5秒延长至4.0秒。
有没有办法在NSThread中表明不合并?或者至少表明允许的最大合并变化?
请参阅以下代码以供参考:
+(void)keepAliveThread
{
@autoreleasepool {
void (^keepAlive)() = ^ (){
// (snipped!) do something...
};
dispatch_queue_t mainQueue = dispatch_get_main_queue();
while( [NSThread currentThread].isCancelled == NO )
{
@autoreleasepool {
dispatch_async(mainQueue, keepAlive);
[NSThread sleepForTimeInterval:1.5];
}
}
}
}
答案 0 :(得分:8)
Apple Developer论坛上的用户实际上建议我观看来自WWDC 2013的视频,题为"使用App Nap提高电源效率&#34 ;;我在其中找到了解决方案:
static dispatch_source_t _keepAliveTimer;
+(void)enable
{
_keepAliveTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, dispatch_get_main_queue());
dispatch_source_set_event_handler(_keepAliveTimer, ^{
// do something
});
dispatch_source_set_timer(_keepAliveTimer, dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC), 1.5 * NSEC_PER_SEC, 0.5 * NSEC_PER_SEC);
dispatch_resume(_keepAliveTimer);
}
这段代码无论LSUIElement状态如何都会以1.5秒(给出或持续0.5秒)触发计时器,并且会阻止App Nap仅为该计时器启动。
答案 1 :(得分:6)
听起来您在没有设置适当的.plist
密钥的情况下运行后台应用程序。
如果您使用的是后台应用程序,那么您必须设置“应用程序是代理程序(UIElement)”' (LSUIElement
)选项为“是”或“应用程序仅为后台”' (LSBackgroundOnly
)在应用程序的plist中选择yes,否则它将受App Nap的限制,这是您在这种情况下遇到的情况。我不希望定时器合并在定时器间隔中产生巨大的间隙。
LSUIElement适用于可能只有浮动窗口或状态栏项目的应用程序。他们没有菜单栏,他们也没有获得停靠栏图标。
App Nap旨在影响前期用户应用程序。根据文档,有4件事会导致应用程序被发送到app-nap:
如果您想阻止用户应用程序遇到App nap,那么您将不得不遵循其中一种支持的机制,导致其中一种状态无效。
如果您使用IOPmlib.h API,则可以为您的应用创建电源管理声明,以防止误打扰。
Alternativaly,您可以使用以下方法禁用自动终止:
[[NSProcessInfo processInfo] disableAutomaticTermination:@"Good Reason"];
并再次启用自动终止:
[[NSProcessInfo processInfo] enableAutomaticTermination:@"Good Reason"];
但这通常用于需要在考虑应用程序之前完成的代码,并且很好地停止'例如写出偏好。
Apple会在文档的某处说明,如果您的应用遇到与app nap相关的问题,您应该提交雷达,以便确定它是否是实施中的错误。