13

我有一个后台应用程序,它需要每 1.5 秒向另一个进程发送一次保持活动状态。在 OSX 10.7 和 10.8 中一切正常,但在 OSX 10.9 下,许多保持活动通知被遗漏,有时最多 3 个。通常在前 3 或 4 分钟一切正常,然后开始出现问题。

经过进一步检查,OSX Mavericks 的“Timer Coalescing”功能似乎负责将请求的 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];
            }
        }
    }
}
4

2 回答 2

8

Apple 开发者论坛上的一位用户实际上推荐我观看 WWDC 2013 上题为“通过 App Nap 提高电源效率”的视频;我在其中找到了解决方案:

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 仅针对该计时器启动。

于 2013-10-25T11:30:36.707 回答
6

听起来您正在运行后台应用程序而没有设置适当的.plist键。

如果您使用的是后台应用程序,则必须在应用程序的 plist 中将“应用程序是代理 (UIElement)”( LSUIElement) 选项设置为“是”或“应用程序仅在后台”( LSBackgroundOnly) 选项设置为“是”,否则将受到到 App Nap,这就是您在这种情况下所经历的。我不希望计时器合并会在计时器间隔中产生巨大的间隙。

LSUIElement 适用于可能只有浮动窗口或状态栏项目的应用程序。他们没有菜单栏,也没有停靠图标。

App Nap 旨在影响前期用户应用程序。根据文档,有 4 件事会导致应用程序被发送到 app-nap:

  • 它是不可见的——如果一个应用程序的所有窗口都被其他窗口隐藏或在隐藏的 Dock 中最小化,并且该应用程序不在前台
  • 听不见
  • 它没有明确禁用自动终止
  • 它没有采取任何电源管理断言

如果您想阻止用户应用程序经历 App nap,那么您将必须遵循一种受支持的机制来导致这些状态之一不处于活动状态。

如果您使用IOPmlib.h API,您可以为您的应用创建一个电源管理断言,以防止应用打盹。

或者,您可以使用以下方法禁用自动终止:

[[NSProcessInfo processInfo] disableAutomaticTermination:@"Good Reason"];

并再次启用自动终止:

[[NSProcessInfo processInfo] enableAutomaticTermination:@"Good Reason"];

但这通常适用于在应用程序被认为“好停止”之前需要完成的代码,例如写出偏好。

Apple 确实在文档中的某处声明,如果您的应用程序遇到与应用程序打盹相关的问题,您应该提交一个雷达,以便确定它是否是其实施中的错误。

于 2013-10-24T23:17:36.870 回答