【问题标题】:How to know if a task is executing in background如何知道任务是否在后台执行
【发布时间】:2012-08-25 12:40:43
【问题描述】:

在我的应用中,我在一个方法上下载了大量图像。

我正在使用一个

 downloadTask = [[UIApplication sharedApplication]
                   beginBackgroundTaskWithExpirationHandler:^{

                       [[UIApplication sharedApplication] endBackgroundTask:downloadTask]; 
                       downloadTask = UIBackgroundTaskInvalid;

                   }]; 

这工作正常,如果我按主页或睡眠按钮,图像会继续下载。

我在 UIAlertView 内的 UIProgressView 中显示进度,当百分比为 100% 时,alertView 被拒绝,我将 viewController 更改为显示下载图像的其他位置。 但我只希望在下载完成时应用真正处于活动状态时发生这种情况。

我一直在查看应用程序的状态,并且在屏幕关闭的情况下下载。

[UIApplication sharedApplication].applicationState

在所有下载过程中状态为 UIApplicationStateActive

我如何知道屏幕是关闭还是打开时进行下载?

接受答案后编辑:

我刚刚发现,如果我点击主页按钮,应用程序会进入 UIApplicationStateBackground,如果我点击唤醒/睡眠,它会进入 UIApplicationStateInactive

按照正确答案的方法,我的应用在这两种情况下都会继续下载。

【问题讨论】:

    标签: iphone objective-c ios ipad background


    【解决方案1】:

    屏幕关闭有两种状态(除了应用程序还没有打开的时候):

    • suspended :在这种情况下,您不必担心,因为在应用再次激活之前不会继续下载;它将在
    • 时进入此状态
    • background:在进入挂起之前,它会在有限的时间内处于此状态,并且此时屏幕已经关闭。在这里您可能要检查是否执行您所说的所有事情,因为在此状态下代码仍然可以执行。在此状态下,应用状态为 UIApplicationStateBackground,因此您只需执行如下检查:

    您可能想要检查应用程序是否在后台执行以达到结果。就像这样:

    if([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
      // Do stuff  
    }
    

    如果它在后台,则屏幕关闭。

    更新:经过几次测试,我发现您遇到的行为可能是由于在主线程上执行下载所致。

    您应该(例如)在全局队列上发送下载。这样应用就会按预期进入后台状态:

    ....
    [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:self.bti];
        }];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self doBackgroundStuff];
    });
    ....
    

    这样,如果在下载过程中将应用程序置于后台,应用程序状态将变为UIApplicationStateBackground,然后您可以像我最初写的那样检查它。如果您在进度期间进行 UI 更新,请记住将它们发送回主线程(因为现在下载在不同的线程上)。

    【讨论】:

    • 但似乎使用beginBackgroundTaskWithExpirationHandler,应用程序在任务完成之前不会进入后台模式,但屏幕是关闭的。如果我启动下载任务并关闭屏幕,它始终处于 UIApplicationStateActive 状态并下载所有图像
    • 嗯,这看起来很奇怪......在 doBackgroundStuff 中,您应该只调用开始下载的函数。那么,在连接处理程序中,应该检查应用程序状态以查看它是否为后台。如果它不起作用,您能否发布更多代码?因为你的案子一定有我遗漏的东西
    • 按照您的说法,应用程序进入后台并在继续下载时变为非活动状态。在 UIApplicationStateInactive 状态下进行屏幕关闭下载。现在是我一直在寻找的东西,但至少现在看来,现在我可以看到应用程序在下载时是处于活动状态还是非活动状态,并且在我打开屏幕时继续按预期工作,所以我接受它是有效的回答。谢谢。
    • 对不起,我删除了一条评论,但您似乎在我删除之前阅读了它,我错了。
    【解决方案2】:

    您可以通过在指定的应用程序委托方法applicationDidEnterBackground:applicationWillEnterForeground: 中设置一个标志来检查您的应用程序是否在后台运行。示例:

    - (void)applicationDidEnterBackground:(UIApplication *)application
        _applicationRunsInForeground = NO;
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application {
        _applicationRunsInForeground = YES;
    }
    

    如果您不想在应用程序委托中包含此 _applicationRunsInForeground 标志,则可以在视图控制器类中观察委托的 NSNotifications(UIApplicationWillEnterForegroundNotificationUIApplicationDidEnterBackgroundNotification)。

    【讨论】:

    • 问题是,应用程序完成后台任务后才会调用applicationDidEnterBackground
    • 那是不可能的。当用户点击主页按钮或用户按下设备上的睡眠/唤醒按钮时,将始终调用 applicationDidEnterBackground 委托方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多