为啥即使应用程序状态是 UIApplicationStateBackground,backgroundTimeRemaining 也会给出 DBL_MAX?

Posted

技术标签:

【中文标题】为啥即使应用程序状态是 UIApplicationStateBackground,backgroundTimeRemaining 也会给出 DBL_MAX?【英文标题】:Why backgroundTimeRemaining gives DBL_MAX even if application state is UIApplicationStateBackground?为什么即使应用程序状态是 UIApplicationStateBackground,backgroundTimeRemaining 也会给出 DBL_MAX? 【发布时间】:2016-11-18 10:16:51 【问题描述】:

每次我的应用程序从挂起模式唤醒时,我都会记录(写入文件)backgroundTimeRemaining 值,就在我开始使用过期处理程序的 UIApplication 后台任务之前,就像这样(在我发出网络请求的方法中):

if([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)

        [Logger logIntoFileNamed:@"log" withContent:[NSString stringWithFormat:@" state %ld, background time remaining %.2f",(long)[[UIApplication sharedApplication] applicationState],[[UIApplication sharedApplication] backgroundTimeRemaining ]] andPrettyTime:true];

        UIApplication*    app = [UIApplication sharedApplication];

        __block UIBackgroundTaskIdentifier task = [app beginBackgroundTaskWithExpirationHandler:^

            [app endBackgroundTask:task];
            task = UIBackgroundTaskInvalid;

            [Logger logIntoFileNamed:@"log" withContent:@" expiration handler executed " andPrettyTime:true];
        ];
    

根据文档,如果应用程序在前台,backgroundTimeRemaining 的值可能很大:

当应用在前台运行时,此属性中的值 保持适当的大。

但这里不是这样。我的方法被执行是因为应用程序状态等于UIApplicationStateBackground。 我在这里错过了什么?

【问题讨论】:

刚刚检查过...当这种情况发生时,我实际上在Thread 1 上。哪个应该是主线程(当我从applicationDidEnterBackground: 运行这段代码时,它会显示Thread 5)。问题是,我不是编写这部分代码的人,我想,因为我确信应用程序从挂起模式中被唤醒,所以我目前在后台线程上执行所有这些。 ..必须进行更多调查并查看代码,但如果我在主线程上,那么我会得到正常的结果,对吧? 【参考方案1】:

是的,根据文档:

如果 app 在 前景。

applicationDidEnterBackground 需要一些时间才能提供正确的backgroundTimeRemaining。这应该从 180 左右开始。在带有dispatch_async 的异步线程中运行它并过滤掉前景值(>180)。

- (void)applicationDidEnterBackground:(UIApplication *)application

    if([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
    
        NSLog(@"Multitasking Supported");

        __block UIBackgroundTaskIdentifier background_task;
        background_task = [application beginBackgroundTaskWithExpirationHandler:^ 

            //Clean up code. Tell the system that we are done.
            [application endBackgroundTask: background_task];
            background_task = UIBackgroundTaskInvalid;
        ];

        //To make the code block asynchronous
        dispatch_async(dispatch_get_main_queue(), ^

            //### background task starts
            NSLog(@"Running in the background\n");
            while(TRUE)
            
                //#### Filter Foreground Values
                if ([[UIApplication sharedApplication] backgroundTimeRemaining] < 180) 
                    NSLog(@"Background time Remaining: %f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
                    [NSThread sleepForTimeInterval:1]; //wait for 1 sec
                

            

            //#### background task ends
            //Clean up code. Tell the system that we are done.
            [application endBackgroundTask: background_task];
            background_task = UIBackgroundTaskInvalid;
        );
    
    else
    
        NSLog(@"Multitasking Not Supported");
    


【讨论】:

您是否有记录此内容的链接(关于状态切换延迟)?我在执行任务时也使用了 dispatch_async,我只是离开了它,因为它是在另一个方法中调用的。无论如何,我进行了一些测试,如果我隔离代码并将其放在 applicationDidEnterBackground 内的一个空项目中:一切正常。问题是,这与我目前的设置不同。我在应用程序从挂起模式唤醒后运行此代码。在这种情况下,我得到 DBL_MAX 值。否则,它给出的值 【参考方案2】:

这可能与您记录backgroundTimeRemaining 的方式有关。获得后台任务后尝试投入:

UIApplication *app = [UIApplication sharedApplication];
long appState = (long)app.applicationState;

if (appState == UIApplicationStateBackground) 
   __block UIBackgroundTaskIdentifier task = [app beginBackgroundTaskWithExpirationHandler:^

     [app endBackgroundTask:task];
     task = UIBackgroundTaskInvalid;
     [Logger logIntoFileNamed:@"log" withContent:@" expiration handler executed " andPrettyTime:true];
  ];

  NSTimeInterval backgroundTimeRemaining = app.backgroundTimeRemaining;
  [Logger logIntoFileNamed:@"log" withContent:[NSString stringWithFormat:@" state %ld, background time remaining %.2f", appState, backgroundTimeRemaining] andPrettyTime:true];

【讨论】:

以上是关于为啥即使应用程序状态是 UIApplicationStateBackground,backgroundTimeRemaining 也会给出 DBL_MAX?的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 在设备设置中,如果我更改时间,即使在应用程序后台、已终止状态下也应该得到通知

为啥我的状态值即使在改变状态后也没有改变? [复制]

即使状态没有改变,为啥 setState 会导致太多的重新渲染错误

为啥即使我没有将 vuex 状态绑定到任何 html 输入元素,我的 vuex 状态也会在更改组件级别状态时发生变化?

为啥 iPhone GPS 箭头出现在状态栏中,即使我没有在位置管理器上调用 startUpdatingLocation?

为啥即使在有状态小部件中使用 setstate 也无法获取更新的变量。因为我想在新的 TabBar 选项上更新我的 Container