標籤:des style blog http color 使用 os io
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