Ios 重复长时间运行的后台任务在第一次后台任务后未启动计时器

Ios 重复长时间运行的后台任务在第一次后台任务后未启动计时器,ios,Ios,我尝试通过反复启动计时器来长时间运行后台任务。但后台任务只在第一次正常运行,下一次它将随机连续调用endBackgroundTask方法 我的背景任务代码: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if([self isMultiTaskingSupported]) { NSLog(@

我尝试通过反复启动计时器来长时间运行后台任务。但后台任务只在第一次正常运行,下一次它将随机连续调用endBackgroundTask方法

我的背景任务代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if([self isMultiTaskingSupported])
    {
        NSLog(@"Multitasking Supported");
    }
    else
    {
         NSLog(@"Multitasking Not Supported.");
    }

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[INNOViewController alloc] initWithNibName:@"INNOViewController_iPhone" bundle:nil];
    } else {
        self.viewController = [[INNOViewController alloc] initWithNibName:@"INNOViewController_iPad" bundle:nil];
    }
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    [self startBackgroundTask:application];
}

-(void) startBackgroundTask:(UIApplication *)application
{
    if([self isMultiTaskingSupported]==NO)
    {
        return ;
    }

    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerMethod:) userInfo:nil repeats:YES];

    self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^(void){
        [self endBackgroundTask:application];

        [self startBackgroundTask:application];
    }];
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.

    if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid) {
        [self endBackgroundTask:(UIApplication *)application];
    }
}

-(BOOL) isMultiTaskingSupported
{
    BOOL result = NO;

    //NSLog(@"before %hhd",result);
    //NSLog(@"method exist or not -> %hhd",[[UIDevice currentDevice] respondsToSelector:@selector(isMultiTaskingSupported)]);
    if([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
    {
        NSLog(@"isMultiTaskingSupported method available in sdk");
        result=[[UIDevice currentDevice] isMultitaskingSupported];
        //NSLog(@"after %hhd",result);
    }
    return result;
}


-(void) timerMethod:(NSTimer *)paramSender
{
    NSTimeInterval backgroundTimeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining];

    if(backgroundTimeRemaining == DBL_MAX)
    {
        NSLog(@"Background Time = undetermined");
    }
    else
    {
         NSLog(@"Background Time = %0.02f",backgroundTimeRemaining);
    }
}

-(void) endBackgroundTask:(UIApplication *)application
{
    NSLog(@"endBackgroundTask");
    dispatch_queue_t mainQueue =  dispatch_get_main_queue();

    __weak INNOAppDelegate *weakSelf=self;

    dispatch_async(mainQueue, ^(void){
        //Complete a long background task in AppDelegate
        INNOAppDelegate *strongSelf = weakSelf;

        if(strongSelf != nil)
        {
            [strongSelf.myTimer invalidate];
            [[UIApplication sharedApplication]endBackgroundTask:self.backgroundTaskIdentifier];
            strongSelf.backgroundTaskIdentifier=UIBackgroundTaskInvalid;

            NSLog(@"cleaned BackgroundTask");


        }
    });


}
2013-04-24 08:50:14.510 MultiTasking[651:c07] Background Time = 17.00
2013-04-24 08:50:15.510 MultiTasking[651:c07] Background Time = 16.00
2013-04-24 08:50:16.510 MultiTasking[651:c07] Background Time = 15.00
2013-04-24 08:50:17.510 MultiTasking[651:c07] Background Time = 14.00
2013-04-24 08:50:18.510 MultiTasking[651:c07] Background Time = 13.00
2013-04-24 08:50:19.510 MultiTasking[651:c07] Background Time = 12.00
2013-04-24 08:50:20.510 MultiTasking[651:c07] Background Time = 11.00
2013-04-24 08:50:21.510 MultiTasking[651:c07] Background Time = 10.00
2013-04-24 08:50:22.510 MultiTasking[651:c07] Background Time = 9.00
2013-04-24 08:50:23.510 MultiTasking[651:c07] Background Time = 8.00
2013-04-24 08:50:24.510 MultiTasking[651:c07] Background Time = 7.00
2013-04-24 08:50:25.510 MultiTasking[651:c07] Background Time = 6.00
2013-04-24 08:50:26.510 MultiTasking[651:c07] Background Time = 5.00
2013-04-24 08:50:26.510 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.511 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.512 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.512 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.512 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.513 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.514 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.514 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.515 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.515 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.516 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.516 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.516 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.517 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.518 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.518 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.519 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.519 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.520 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.520 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.521 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.522 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.523 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.523 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.524 MultiTasking[651:c07] endBackgroundTask
日志:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if([self isMultiTaskingSupported])
    {
        NSLog(@"Multitasking Supported");
    }
    else
    {
         NSLog(@"Multitasking Not Supported.");
    }

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[INNOViewController alloc] initWithNibName:@"INNOViewController_iPhone" bundle:nil];
    } else {
        self.viewController = [[INNOViewController alloc] initWithNibName:@"INNOViewController_iPad" bundle:nil];
    }
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

    [self startBackgroundTask:application];
}

-(void) startBackgroundTask:(UIApplication *)application
{
    if([self isMultiTaskingSupported]==NO)
    {
        return ;
    }

    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerMethod:) userInfo:nil repeats:YES];

    self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^(void){
        [self endBackgroundTask:application];

        [self startBackgroundTask:application];
    }];
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.

    if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid) {
        [self endBackgroundTask:(UIApplication *)application];
    }
}

-(BOOL) isMultiTaskingSupported
{
    BOOL result = NO;

    //NSLog(@"before %hhd",result);
    //NSLog(@"method exist or not -> %hhd",[[UIDevice currentDevice] respondsToSelector:@selector(isMultiTaskingSupported)]);
    if([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
    {
        NSLog(@"isMultiTaskingSupported method available in sdk");
        result=[[UIDevice currentDevice] isMultitaskingSupported];
        //NSLog(@"after %hhd",result);
    }
    return result;
}


-(void) timerMethod:(NSTimer *)paramSender
{
    NSTimeInterval backgroundTimeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining];

    if(backgroundTimeRemaining == DBL_MAX)
    {
        NSLog(@"Background Time = undetermined");
    }
    else
    {
         NSLog(@"Background Time = %0.02f",backgroundTimeRemaining);
    }
}

-(void) endBackgroundTask:(UIApplication *)application
{
    NSLog(@"endBackgroundTask");
    dispatch_queue_t mainQueue =  dispatch_get_main_queue();

    __weak INNOAppDelegate *weakSelf=self;

    dispatch_async(mainQueue, ^(void){
        //Complete a long background task in AppDelegate
        INNOAppDelegate *strongSelf = weakSelf;

        if(strongSelf != nil)
        {
            [strongSelf.myTimer invalidate];
            [[UIApplication sharedApplication]endBackgroundTask:self.backgroundTaskIdentifier];
            strongSelf.backgroundTaskIdentifier=UIBackgroundTaskInvalid;

            NSLog(@"cleaned BackgroundTask");


        }
    });


}
2013-04-24 08:50:14.510 MultiTasking[651:c07] Background Time = 17.00
2013-04-24 08:50:15.510 MultiTasking[651:c07] Background Time = 16.00
2013-04-24 08:50:16.510 MultiTasking[651:c07] Background Time = 15.00
2013-04-24 08:50:17.510 MultiTasking[651:c07] Background Time = 14.00
2013-04-24 08:50:18.510 MultiTasking[651:c07] Background Time = 13.00
2013-04-24 08:50:19.510 MultiTasking[651:c07] Background Time = 12.00
2013-04-24 08:50:20.510 MultiTasking[651:c07] Background Time = 11.00
2013-04-24 08:50:21.510 MultiTasking[651:c07] Background Time = 10.00
2013-04-24 08:50:22.510 MultiTasking[651:c07] Background Time = 9.00
2013-04-24 08:50:23.510 MultiTasking[651:c07] Background Time = 8.00
2013-04-24 08:50:24.510 MultiTasking[651:c07] Background Time = 7.00
2013-04-24 08:50:25.510 MultiTasking[651:c07] Background Time = 6.00
2013-04-24 08:50:26.510 MultiTasking[651:c07] Background Time = 5.00
2013-04-24 08:50:26.510 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.511 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.512 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.512 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.512 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.513 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.514 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.514 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.515 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.515 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.516 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.516 MultiTasking[651:c07] cleaned BackgroundTask
2013-04-24 08:50:26.516 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.517 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.518 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.518 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.519 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.519 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.520 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.520 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.521 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.522 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.523 MultiTasking[651:c07] endBackgroundTask
2013-04-24 08:50:26.523 MultiTasking[651:c07] isMultiTaskingSupported method available in sdk
2013-04-24 08:50:26.524 MultiTasking[651:c07] endBackgroundTask

这可能是由于您的过期处理程序块结束了任务,然后又重新启动了任务。


此外,您仍然在
endBackgroundTask
块中捕获
self
(使用
strongSelf.backgroundTaskIdentifier

这可能是由于您的过期处理程序块结束了任务,然后再次启动了任务。


此外,您仍然在
endBackgroundTask
块中捕获
self
(使用
strongSelf.backgroundTaskIdentifier

是的,在第一个后台任务完成后我需要再次启动后台任务调用过期处理程序时,您不应该启动另一个任务。您应该停止后台执行(清理)。我需要继续运行后台任务。你不能,苹果不允许无休止地执行BG(除非你注册为音频播放器或导航应用程序[AFAIK])。是的,我需要在第一个后台任务完成后再次启动后台任务调用过期处理程序时,不应启动另一个任务。您应该停止后台执行(清理)。我需要继续运行后台任务。你不能,苹果不允许无休止地执行BG(除非你注册为音频播放器或导航应用程序[AFAIK])。你最终得到了这个工作,还是不可能?你最终得到了这个工作,还是不可能?