zoukankan      html  css  js  c++  java
  • 让程序支持后台处理

    iOS支持4种主要的后台处理:应用程序挂起、本地通知、任务特定的后台处理和完成长时间运行的后台任务。

    iOS4.0以后的设备都已经支持多任务了,如果项目要在更早版本的系统中运行,可以通过下面代码检测设备是否支持多任务:

    UIDevice *device = [UIDevice currentDevice];
    BOOL backgroundSupported = NO;
    if([device respondsToSelector:@selector(isMultitaskingSupported)])
    {
        backgroundSupported = device.multitaskingSupported;
    }

    先来看一下如何禁用后台处理:

    如图所示,在info选项卡的Custom iOS Target Properties属性列表里添加一个新行:”Application does not run in background”,并将值设为YES即可禁用后台处理。

     

    挂起

    应用程序挂起时,它将暂停执行代码,但保留当前状态。用户返回到应用程序时,它看起来像是一直在运行。实际上,所有的任务都停止了,以免应用程序占用设备的资源。

    在应用程序挂起时,除执行清理工作外,还需要负责从挂起状态恢复,并更新在挂起期间将发生变化的应用程序内容(时间/日期等)。

    任何应用程序都默认支持后台挂起。为支持后台挂起,只需利用开发工具创建iOS4.0以上的项目即可。

    可以创建一个计时器程序,当计数为10时,按home键退出程序,这样你过一段时间再返回程序,发现会从10开始继续计数,而不是挂起时仍然在继续计数。

     

    本地通知

    下面的代码演示了本地通知的使用,一旦生效,即使程序并没有运行,也会按设定的触发通知。

    [[UIApplication sharedApplication] cancelAllLocalNotifications];
    
    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
    localNotif.applicationIconBadgeNumber = 1;
    localNotif.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];
    localNotif.timeZone = [NSTimeZone defaultTimeZone];
    localNotif.repeatInterval = NSMinuteCalendarUnit;
    localNotif.soundName = @"msg.wav";
    localNotif.alertBody = @"This is a notice!";
    
    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
    UILocalNotification *localNotif = [[UILocalNotification alloc] init];

    这行代码取消了应用程序以前可能调度了的所有通知,以提供干净的平台。

    UILocalNotification类的各属性释义:

    applicationIconBadgeNumber — 触发通知时显示在应用程序图标中的徽章计数。

    fireDate — 一个NSDate对象,指定通知将在未来的什么时间触发。

    timeZone — 用于调度通知的时区。几乎总是设置为本地时区,即[NSTimeZone defaultTimeZone]。

    repeatInterval — 重复触发通知的频率。可选择的值可能有NSDayCalendarUnit(每天)、NSHourCalendarUnit(每小时)、和NSMinuteCalendarUnit(每分钟)等。

    soundName — 一个字符串(NSString),包含通知触发时将播放的声音源。

    alertBody — 一个字符串,包含要向用户显示的文本消息。

     

    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];

    开始调度通知

     

    任务特定的后台处理

    这种情况有一个很典型的应用,就是后台音乐播放:我们在程序里播放一首歌曲,当按下Home键或屏幕进入待机,我们仍然希望音乐继续播放。

    首先建立简单代码:

    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic,strong) AVAudioPlayer *audioPlayer;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        //播放音频之前先要设置AVAudioSession模式,设为AVAudioSessionCategoryPlayback即可。模式意义及其他模式请参考文档。
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setActive:YES error:nil];
        [session setCategory:AVAudioSessionCategoryPlayback error:nil];
        
        NSString *strSoundFile = [[NSBundle mainBundle] pathForResource:@“mymusic1” ofType:@"mp3"];
        
        self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:strSoundFile] error:nil];
        self.audioPlayer.delegate = self;
        [self.audioPlayer play];
    }
    
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
    {
        NSLog(@"播放结束");
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    @end

    然后需要选择项目的顶级编组,并单击目标—项目名,展开Custom iOS Target Properties选项卡,在属性列表里添加一行名为”Required background modes”的Key,然后展开这个键,在其中添加一个新值:”App plays audio or streams audio/video using AirPlay”。

    修改保存后,再次运行程序,并按下home键返回,将发现音乐会继续在后台播放。另一个比较典型的应用就是定位服务,需要添加”App registers for location updates”。

     

    完成长时间运行的后台任务

    对于每项要启用后台完成的任务,都需要有自己的UIBackgroundTaskIdentifier。初始化方式如下:

    UIBackgroundTaskIdentifier counterTask = [[UIApplication sharedApplication]
                                             beginBackgroundTaskWithExpirationHandler:^{
                                                    //超时后的处理
                                                    NSLog(@"超时");
                                             }];

    完成初始化的同时也正式开启了后台处理,要停止后台处理,可以做如下操作:

    [[UIApplication sharedApplication] endBackgroundTask:self.counterTask];

    每个程序的后台处理时间是有限的,一般只有几分钟;通过UIApplication的backgroundTimeRemaining属性可以查询后台处理剩余时间:

    NSTimeInterval timeInterval = [[UIApplication sharedApplication] backgroundTimeRemaining];
    
    int hour = (int)(timeInterval/3600);
    int minute = (int)(timeInterval - hour*3600)/60;
    int second = timeInterval - hour*3600 - minute*60;
    
    NSLog(@"%@",[NSString stringWithFormat:@"%d时%d分%d秒", hour, minute,second]);

    下面创建了一个不停计数的程序,运行后尝试退出程序(不是结束程序),过一段时间后返回程序,发现计数还在后台进行,而不是像之前挂起那样暂停计数:

    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic) UIBackgroundTaskIdentifier counterTask;
    @property (strong, nonatomic) IBOutlet UILabel *lblNum;
    @property (nonatomic) int count;
    @property (nonatomic,weak) NSTimer *myTimer;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.counterTask = [[UIApplication sharedApplication]
                                                 beginBackgroundTaskWithExpirationHandler:^{
                                                        //超时后的处理
                                                        NSLog(@"超时");
                                                 }];
        
        self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countUp) userInfo:nil repeats:YES];
    }
    
    - (void)countUp
    {
        if(self.count==600)
        {
            [self.myTimer invalidate];
            [self setMyTimer:nil];
            [[UIApplication sharedApplication] endBackgroundTask:self.counterTask];
        }
        else
        {
            self.count++;
            self.lblNum.text = [[NSString alloc] initWithFormat:@"%d",self.count];
        }
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end

     

  • 相关阅读:
    SVN使用指引(Windows)
    Android开发14——监听内容提供者ContentProvider的数据变化
    Android开发13——内容提供者ContentProvider的基本使用
    Android开发12——Andorid中操作数据库的insert的两种方法以及nullColumnHack
    Android开发11——手机横屏和竖屏与android:configChanges
    Android开发10——Activity的跳转与传值
    Android开发9——Activity的启动模式
    Android开发8——利用pull解析器读写XML文件
    Android开发7——android.database.CursorIndexOutOfBoundsException:Index -1 requested
    Android开发6——布局中的wrap_content和fill_parent以及match_parent
  • 原文地址:https://www.cnblogs.com/CoderWayne/p/3910322.html
Copyright © 2011-2022 走看看