NSTimer在后台运行

作者: 天天想念 | 来源:发表于2016-09-07 10:40 被阅读787次

    在iOS中应用进入后台,系统会将整个应用当前的状态以快照的形式保存起来,也就是常说的"墓碑"机制。此时对应的定时器也就直接被关闭了,如果我们需要在后台保持一段时间运行,我们就需要做对应的处理。
    在iOS中应用进入后台,app都有3分钟左右的后台任务执行时间。 3分钟后,app会被iOS强行挂起。

    除了

    • 音乐应用
    • 电话之类
    • GPS定位

    的app可以保持一个长久的后台运行。当你提交app到App Store时,苹果会审查你的app,一旦发现你“滥用”了后台API,你的app将被拒绝。也即是说你在info.plist 设置这几种backgroundmode,你的程序必须含有这些功能,你的程序才会有审核通过。

    一般情况下,3分钟的后台时间足够我们处理我们的应用数据了。
    定时器在这3分钟的时间内保持不间断的运行。

    方法1

    在app的代理中添加如下代码

    - (void)applicationDidEnterBackground:(UIApplication *)application {
        if ( [self isMutiltaskingSupported] == NO) {
            NSLog(@"---> 不支持后台多任务");
            return;
        }
        
        UIApplication*   app = [UIApplication sharedApplication];
        __block    UIBackgroundTaskIdentifier bgTask;
        bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
            dispatch_async(dispatch_get_main_queue(), ^{
                if (bgTask != UIBackgroundTaskInvalid)
                {
                    bgTask = UIBackgroundTaskInvalid;
                }
            });
        }];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                if (bgTask != UIBackgroundTaskInvalid)
                {
                    bgTask = UIBackgroundTaskInvalid;
                }
            });
        });
    }
    

    当然你需要判断你的设备是否支持后台(不支持多任务情况现在基本可以忽略)

    // 判断当前设备是否支持 后台多任务
    - (BOOL)isMutiltaskingSupported{
        BOOL result = NO;
        if ( [[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
            result = [[UIDevice currentDevice] isMultitaskingSupported];
        }
        return result;
    }
    
    方法2

    在网上搜索了下,基本上实现方式都差不多。这里直接代码贴出,以备以后查阅

    #import "AppDelegate.h"
    
    @interface AppDelegate ()
    @property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
    @property (nonatomic, strong) NSTimer * myTimer;
    
    @end
    
    @implementation AppDelegate
    
    // 判断当前设备是否支持 后台多任务
    - (BOOL)isMutiltaskingSupported{
        BOOL result = NO;
        if ( [[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)]) {
            result = [[UIDevice currentDevice] isMultitaskingSupported];
        }
        return result;
    }
    // 定时器调用方法
    - (void)timerMethod:(NSTimer *)paramSender{
        NSTimeInterval backgroundTimeRemanging = [[UIApplication sharedApplication] backgroundTimeRemaining];
        if ( backgroundTimeRemanging == DBL_MAX) {
            NSLog(@"Background Time Remaining = Undeterminded");
        }
        //--显示后台任务还剩余的时间
        NSLog(@"Background Timer Remaining = %.02f Seconds", backgroundTimeRemanging);
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        NSTimeInterval backgroundTimeRemanging = [[UIApplication sharedApplication] backgroundTimeRemaining];
        NSLog(@"backgroundTimeRemanging = %.02f", backgroundTimeRemanging);
        
        if ( [self isMutiltaskingSupported] == NO) {
            NSLog(@"---> 不支持后台多任务");
            return;
        }
        
        self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{
            [self endBackgroundTask];
        }];
        self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerMethod:) userInfo:nil repeats:YES];
    }
    
    // 任务完成,处理释放对象
    - (void)endBackgroundTask{
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
        __weak AppDelegate *weakSelf = self;
        dispatch_async(mainQueue, ^{
            AppDelegate * strongSelf = weakSelf;
            if (strongSelf != nil) {
                [strongSelf.myTimer invalidate];
                [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
                strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
            }
        });
    }
    
    // 进入前台,停止任务
    - (void)applicationDidBecomeActive:(UIApplication *)application {
        if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){
            [self endBackgroundTask];
        }
    }
    @end
    

    参考链接
    参考1

    相关文章

      网友评论

        本文标题:NSTimer在后台运行

        本文链接:https://www.haomeiwen.com/subject/vldjettx.html