IOs7应用程序崩溃时在后台 [英] IOs7 app crashing when in background

查看:353
本文介绍了IOs7应用程序崩溃时在后台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程式有时在背景时会当机,并显示以下当机纪录:

  Nov 8 12:33:31 iPad backboardd [29]< Warning> ;: MyApp [3096]具有超出允许时间的活动断言:
{(
identifier:MyApp调用,来自 - [AppDelegate applicationDidEnterBackground:] process: MyApp [3096] permittedBackgroundDuration:180.000000 reason:finishTask owner pid:3096 preventSuspend preventIdleSleep preventSuspendOnSleep
)}

通过其他问题,我发现崩溃消息表明我



因此我添加了一些NSLogs:

   - (void)applicationDidEnterBackground:(UIApplication *)application 
{
[self saveContext];
[设置setCallLock:YES];

[self saveStuff];

if([self isBackgroundTaskNeeded])
{

UIApplication * app = [UIApplication sharedApplication];

bgTask = [app beginBackgroundTaskWithExpirationHandler:^ {

[self pauseDownloads];

NSLog(@Debug - 结束后台任务%d,bgTask);
[app endBackgroundTask:bgTask];
NSLog(@Debug - 后台任务%d已结束,bgTask);
bgTask = UIBackgroundTaskInvalid;


}];
NSLog(@Debug - 启动后台任务%d,bgTask);
[self initBackground];

}

}

该任务在崩溃时被调用两次:

  Nov 7 12:30:02 iPad MyApp [3096]< Warning> :Debug  - 启动后台任务7 
Nov 7 12:30:30 iPad MyApp [3096]< Warning> ;: Debug - 启动后台任务8
Nov 7 12:33:26 iPad MyApp [3096] <警告> ;:调试 - 结束后台任务8
Nov 7 12:33:26 iPad MyApp [3096]<警告> ;:调试 - 后台任务8结束
Nov 7 12:33:26 iPad MyApp [3096]<警告> ;:调试 - 结束后台任务0
Nov 7 12:33:26 iPad MyApp [3096]<警告> ;:调试 - 后台任务0结束

我不能告诉双重调用何时发生,为什么。所以问题是,为什么任务被调用两次,是否有办法避免它?



编辑:

   - (void)pauseDownloads 
{
for(AFDownloadRequestOperation * operation in self.operationQueue.operations)
{
if isPaused])
{
[operation pause];
}
}
}


解决方案>

您应该endBackground没有到期。

  UIApplication * app = [UIApplication sharedApplication]; 

bgTask = [app beginBackgroundTaskWithExpirationHandler:^ {

[self pauseDownloads];

NSLog(@Debug - 结束后台任务%d,bgTask);
[app endBackgroundTask:bgTask];
NSLog(@Debug - 后台任务%d已结束,bgTask);
bgTask = UIBackgroundTaskInvalid;


}];
NSLog(@Debug - 启动后台任务%d,bgTask);

[self initBackground];

NSLog(@Debug - 结束后台任务%d未到期,bgTask);
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;

当应用程序进入前台时,请将此平衡 endBackgroundTask call -

   - (void)applicationWillEnterForeground:(UIApplication *)application 
{
if bgTask!= UIBackgroundTaskInvalid){
NSLog(@Debug - 结束后台任务%d没有到期(当applicationWillEnterForeground),bgTask);
[app endBackgroundTask:bgTask]
bgTask = UIBackgroundTaskInvalid
}

//此外,要计数到期处理程序pauseDownloads调用,请考虑在此恢复下载(或applicationDidBecomeActive应用程序委托)。
}

因为 - 到期处理程序当后台任务到期(通常最多10分钟,但不能保证)时执行{}。我假设你的实际后台任务是 [self initBackground]; ,否则你应该把它放在块之外 endBackgroundTask



此外,我注意到您的pauseDownloads代码,现在,似乎你正在使用NSOperationQueue当应用程序在后台执行下载。在这种情况下,请确保在完成下载或执行到期处理程序之后,不会调用 endBackgroundTask 。换句话说,控件不会返回太早,这意味着您可能需要监视这些下载的NSOperation。


My app sometimes crashes when in background and shows the following crash log:

Nov  7 12:33:31 iPad backboardd[29] <Warning>: MyApp[3096] has active assertions beyond permitted time: 
    {(
        <BKProcessAssertion: 0x14680c60> identifier: Called by MyApp, from -[AppDelegate applicationDidEnterBackground:] process: MyApp[3096] permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:3096 preventSuspend  preventIdleSleep  preventSuspendOnSleep 
    )}

Looking through other questions I found out that the crash message indicates that I didn't end a task properly, so when its time expired the OS ended it and crashed my app.

So I added some NSLogs:

- (void)applicationDidEnterBackground:(UIApplication *)application
{       
    [self saveContext];
    [Settings setCallLock:YES];

    [self saveStuff];

    if ([self isBackgroundTaskNeeded]) 
    {

        UIApplication*  app = [UIApplication sharedApplication];

        bgTask = [app beginBackgroundTaskWithExpirationHandler:^{

            [self pauseDownloads];

            NSLog(@"Debug - Ending background task %d",bgTask);
            [app endBackgroundTask:bgTask];
            NSLog(@"Debug -  Background task %d ended",bgTask);
            bgTask = UIBackgroundTaskInvalid;


        }];
        NSLog(@"Debug - Starting background task %d",bgTask);
        [self initBackground];

    }

}

and found out that the task was called twice when it crashed:

Nov  7 12:30:02 iPad MyApp[3096] <Warning>: Debug - Starting background task 7
Nov  7 12:30:30 iPad MyApp[3096] <Warning>: Debug - Starting background task 8
Nov  7 12:33:26 iPad MyApp[3096] <Warning>: Debug - Ending background task 8
Nov  7 12:33:26 iPad MyApp[3096] <Warning>: Debug -  Background task 8 ended
Nov  7 12:33:26 iPad MyApp[3096] <Warning>: Debug - Ending background task 0
Nov  7 12:33:26 iPad MyApp[3096] <Warning>: Debug -  Background task 0 ended

I wasn't able to tell when the double call happens and why. So question is why is the task being called twice and is there a way to avoid it?

Edit:

- (void) pauseDownloads
{
    for (AFDownloadRequestOperation *operation in self.operationQueue.operations)
    {
        if(![operation isPaused])
        {
            [operation pause];
        }
    }
}

解决方案

You should endBackground without expiration..

    UIApplication*  app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{

        [self pauseDownloads];

        NSLog(@"Debug - Ending background task %d",bgTask);
        [app endBackgroundTask:bgTask];
        NSLog(@"Debug -  Background task %d ended",bgTask);
        bgTask = UIBackgroundTaskInvalid;


    }];
    NSLog(@"Debug - Starting background task %d",bgTask);

    [self initBackground];

    NSLog(@"Debug - Ending background task %d without expiration",bgTask);
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;

When app enters in foreground, put this balancing endBackgroundTask call -

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    if (bgTask != UIBackgroundTaskInvalid) {
       NSLog(@"Debug - Ending background task %d without expiration (when applicationWillEnterForeground)",bgTask);
       [app endBackgroundTask:bgTask];
       bgTask = UIBackgroundTaskInvalid;
    }

    // Also, to counter expiration handler pauseDownloads call, consider resuming the downloads here (or applicationDidBecomeActive app delegate).
}

Because - The expiration handler block {} is executed when the background task expire (usually up to 10 min, but not guaranteed). I assume your actual background task is [self initBackground];, otherwise you should put it outside the block and before endBackgroundTask call.

(Another potential issue)

Also, I noticed your pauseDownloads code now, it seems you are performing downloads using NSOperationQueue when app goes in background. In such a case, ensure that the endBackgroundTask is not called until you have finished downloading or expiration handler is executed. In other words, the control doesn't return too early which means you might need to monitor these download NSOperation(s).

这篇关于IOs7应用程序崩溃时在后台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆