如何解决iOS后台应用程序取消无法解决? [英] How to troubleshoot iOS background app fetch not working?

查看:112
本文介绍了如何解决iOS后台应用程序取消无法解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将iOS后台应用程序提取到我的应用程序中。在Xcode中进行测试时,它可以正常运行,但在设备上运行却没有!

I am trying to get iOS background app fetch to work in my app. While testing in Xcode it works, when running on the device it doesn't!


  • 我的测试设备运行的是iOS 9.3.5(我的部署目标是7.1)

  • 我在Xcode中的目标功能下的后台模式下启用了后台获取

在应用程序中:didFinishLaunchingWithOptions我尝试了使用setMinimumBackgroundFetchInterval的各种间隔,包括UIApplicationBackgroundFetchIntervalMinimum

In application:didFinishLaunchingWithOptions I have tried various intervals with setMinimumBackgroundFetchInterval, including UIApplicationBackgroundFetchIntervalMinimum

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    // tell the system we want background fetch
    //[application setMinimumBackgroundFetchInterval:3600]; // 60 minutes
    [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
    //[application setMinimumBackgroundFetchInterval:1800]; // 30 minutes

    return YES;
}

我已经实现了应用程序:performFetchWithCompletionHandler

I have implemented application:performFetchWithCompletionHandler

void (^fetchCompletionHandler)(UIBackgroundFetchResult);
NSDate *fetchStart;

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    fetchCompletionHandler = completionHandler;

    fetchStart = [NSDate date];

    [[NSUserDefaults standardUserDefaults] setObject:fetchStart forKey:kLastCheckedContentDate];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [FeedParser parseFeedAtUrl:url withDelegate:self];
}

 -(void)onParserFinished
{
    DDLogVerbose(@"AppDelegate/onParserFinished");

    UIBackgroundFetchResult result = UIBackgroundFetchResultNoData;

    NSDate *fetchEnd = [NSDate date];
    NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
    DDLogVerbose(@"Background Fetch Duration: %f seconds", timeElapsed);
    if ([self.mostRecentContentDate compare:item.date] < 0) {
        DDLogVerbose(@"got new content: %@", item.date);
        self.mostRecentContentDate = item.date;
        [self scheduleNotificationWithItem:item];
        result = UIBackgroundFetchResultNewData;
    }
    else {
        DDLogVerbose(@"no new content.");
        UILocalNotification* localNotification = [[UILocalNotification alloc] init];
        localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:60];
        localNotification.alertBody = [NSString stringWithFormat:@"Checked for new posts in %f seconds", timeElapsed];
        localNotification.timeZone = [NSTimeZone defaultTimeZone];
        [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    }

    fetchCompletionHandler(result);
}




  • 我有(成功!)使用Xcode的Debug / SimulateBackgroundFetch测试模拟器和设备

    • I have (successfully!) tested with the simulator and device using Xcode's Debug/SimulateBackgroundFetch

      我已成功测试了一个新方案,如另一个SO答案所示( https://stackoverflow.com/a/29923802/519030

      I have successfully tested with a new scheme as shown in another SO answer (https://stackoverflow.com/a/29923802/519030)

      在设备上运行但未连接到Xcode时,我的代码没有执行。我打开了应用程序,关闭了应用程序(没有杀死应用程序!),等待了几个小时和几天。我已经尝试登录fetch handers,还编写了代码来发送本地通知。

      When running on the device and not connected to Xcode, my code is not executing. I've opened the app, closed the app (not killed the app!), waited hours and days. I have tried logging in the fetch handers, and also written code to send local notifications.

      我曾经成功地在设备上看到了我的本地通知测试,事实上iOS似乎触发三次获取,每次大约相隔大约十五分钟,但之后再也没有发生过。

      I once successfully saw my local notifications test on the device, and in fact iOS seemed to trigger the fetch three times, each about about fifteen minutes apart, but then it never occurred again.

      我知道用于确定允许后台获取的频率的算法发生是一个谜,但我希望它能在一段时间内偶尔运行。

      I know the algorithm used to determine how frequently to allow the background fetch to occur is a mystery, but I would expect it to run at least occasionally within a span of days.

      我对其他测试或者如何测试感到茫然解决为什么它似乎在模拟器中工作但不在设备上工作。

      I am at a loss for what else to test, or how to troubleshoot why it seems to work in the simulator but not on the device.

      感谢任何建议!

      推荐答案

      您的问题是您在调用完成处理程序之前从 performFetchWithCompletionHandler 返回,因为网络提取操作正在后台进行并在您的委托方法中调用完成处理程序d。由于iOS认为您不遵守规则,因此会拒绝您使用后台获取功能。

      Your problem is that you are returning from performFetchWithCompletionHandler before you call the completion handler, since the network fetch operation is occurring the in the background and you call the completion handler in your delegate method. Since iOS thinks you aren't playing by the rules it will deny your ability to use background fetch.

      要解决此问题,您需要调用 beginBackgroundTaskWithExpirationHandler 然后在调用完成处理程序后结束该任务。

      To fix the problem you need to call beginBackgroundTaskWithExpirationHandler and then end that task after you have called the completion handler.

      类似于:

      UIBackgroundTaskIdentifier backgroundTask
      
      -(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
      {
          fetchCompletionHandler = completionHandler;
      
          fetchStart = [NSDate date];
      
          self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
              [application endBackgroundTask:self.backgroundUpdateTask];
              self.backgroundTask = UIBackgroundTaskInvalid;
          }];
      
          [[NSUserDefaults standardUserDefaults] setObject:fetchStart forKey:kLastCheckedContentDate];
      
          [FeedParser parseFeedAtUrl:url withDelegate:self];
      }
      
      -(void)onParserFinished
      {
          DDLogVerbose(@"AppDelegate/onParserFinished");
      
          UIBackgroundFetchResult result = UIBackgroundFetchResultNoData;
      
          NSDate *fetchEnd = [NSDate date];
          NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
          DDLogVerbose(@"Background Fetch Duration: %f seconds", timeElapsed);
          if ([self.mostRecentContentDate compare:item.date] < 0) {
              DDLogVerbose(@"got new content: %@", item.date);
              self.mostRecentContentDate = item.date;
              [self scheduleNotificationWithItem:item];
              result = UIBackgroundFetchResultNewData;
          }
          else {
              DDLogVerbose(@"no new content.");
              UILocalNotification* localNotification = [[UILocalNotification alloc] init];
              localNotification.alertBody = [NSString stringWithFormat:@"Checked for new posts in %f seconds", timeElapsed];
              [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
          }
          fetchCompletionHandler(result);
          [[UIApplication sharedApplication] application endBackgroundTask:self.backgroundUpdateTask];
          self.backgroundTask = UIBackgroundTaskInvalid;
      }
      

      我使用这种方法的测试应用程序最初每15分钟执行一次获取,但随着时间的推移它变得不那么频繁如果没有后台任务,它会显示您遇到的相同问题。

      My test app using this approach has been executing a fetch every 15 minutes initially, but it becomes less frequent over time. Without the background task it exhibited the same issue you are seeing.

      我发现将后台获取间隔设置为 UIApplicationBackgroundFetchIntervalMinimum 也有帮助。我的测试应用程序正在以3600(一小时)的后台获取间隔运行,并且已经可靠地触发了几天;即使手机重启后又没有再运行应用程序。然而实际的触发间隔是2-3小时。

      I found that setting the background fetch interval to something other than UIApplicationBackgroundFetchIntervalMinimum also helps. My test app is running with a background fetch interval of 3600 (one hour) and has been reliably triggering for several days now; even after a phone restart and not running the app again. The actual trigger interval is 2-3 hours however.

      我的示例应用程序是这里

      这篇关于如何解决iOS后台应用程序取消无法解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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