iOS應(yīng)用的后臺(tái)任務(wù)

因?yàn)閕OS系統(tǒng)的特殊性,它不像安卓、Windows等其它操作系統(tǒng)一樣,能在應(yīng)用退入后臺(tái)還能啟動(dòng)一些后臺(tái)任務(wù)處理一些事件。iOS系統(tǒng)在應(yīng)用退到后臺(tái),也就是按下Home鍵之后,應(yīng)用的所有任務(wù)會(huì)被掛起、暫停,因此在這里對(duì)它的后臺(tái)任務(wù)方式作一些記錄。
iOS系統(tǒng)或許是出于電量的考慮吧,因?yàn)閕Phone手機(jī)的電池容量一直都不大,為了減小功耗,所以它不允許應(yīng)用退入后臺(tái)還留有活的后臺(tái)任務(wù)。當(dāng)然并不是說iOS系統(tǒng)不能進(jìn)行多任務(wù)處理,自iOS7之后,也有好多種能讓應(yīng)用在后臺(tái)處理任務(wù)的方法。

iOS后臺(tái)發(fā)展

在一開始的iOS操作系統(tǒng)上,應(yīng)用沒有后臺(tái),按下Home鍵之后,應(yīng)用就退出了,設(shè)備只能依靠蘋果的APNS與服務(wù)器連結(jié),重新點(diǎn)擊啟動(dòng)之后,應(yīng)用重新載入;
后來的操作系統(tǒng),有了后臺(tái),按下Home鍵之后,應(yīng)用退到后臺(tái),幾秒之后,會(huì)被系統(tǒng)掛起,下次點(diǎn)擊進(jìn)入,會(huì)出現(xiàn)上次退出的界面(當(dāng)然在雙擊Home鍵將應(yīng)用徹底殺死就不能保留數(shù)據(jù)了),保留上次的一些操作,但是仍然不能在退入后臺(tái)做一些相應(yīng)的操作。
再之后就是iOS7之后,雖然不能真正的在后臺(tái)處理一些東西,但是調(diào)用蘋果的一些API,可以在應(yīng)用不打開的時(shí)候做一些后臺(tái)相應(yīng)的操作。

后臺(tái)處理任務(wù)的幾種方式

UIBackgroundTaskIdentifier

這種方式不能讓應(yīng)用真正的一直在后臺(tái)活下去,只能讓應(yīng)用延緩被掛起的時(shí)間,在應(yīng)用已經(jīng)進(jìn)入后臺(tái),做一些善后工作,保存一些現(xiàn)場(chǎng)數(shù)據(jù)。
監(jiān)聽UIApplicationDidEnterBackgroundNotification通知,或者在applicationDidEnterBackground方法中加入以下代碼。

UIApplication *application = [UIApplication  performSelector:@selector(sharedApplication)];
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
    // Clean up any unfinished task business by marking where you
    // stopped or ending the task outright.
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

// Start the long-running task and return immediately.
[self cleanDiskWithCompletionBlock:^{
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

cleanDiskWithCompletionBlock在該方法中啟動(dòng)異步線程,立刻返回,在異步線程中,最后執(zhí)行完成回調(diào)的block。

Background Mode
后臺(tái)模式.png
Background Fetch

后臺(tái)應(yīng)用刷新,在手機(jī)設(shè)置->通用->后臺(tái)應(yīng)用刷新,打開之后,應(yīng)用可以在后臺(tái)不定時(shí)的刷新內(nèi)容。因?yàn)檫@個(gè)機(jī)制也是由蘋果統(tǒng)一管理,而且調(diào)用時(shí)間也是不確定的,所以開發(fā)者很難調(diào)試系統(tǒng)什么時(shí)候會(huì)分配你時(shí)間允許你刷新內(nèi)容。
打開方法
在XCode->TARGETS->Capabilities->Background Modes
選擇Background Fetch打勾,然后在plist文件中Required background modes添加相應(yīng)的字段App registers for location updates
在應(yīng)用啟動(dòng)的代碼中添加

[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];

UIApplicationBackgroundFetchIntervalMinimum
UIApplicationBackgroundFetchIntervalNever
關(guān)于刷新的兩個(gè)參數(shù),一個(gè)是盡可能頻繁的刷新,一個(gè)是從來不刷新,刷新頻率由系統(tǒng)來分配決定,所以可以應(yīng)用在實(shí)時(shí)性不高的場(chǎng)合。
系統(tǒng)會(huì)在刷新應(yīng)用時(shí),調(diào)用appDelegate中下邊的方法,在下邊方法中處理刷新動(dòng)作。

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
//刷新數(shù)據(jù)

completionHandler(UIBackgroundFetchResultNewData);
}

UIBackgroundFetchResultNewData,//刷新到新數(shù)據(jù)
UIBackgroundFetchResultNoData,//沒有新數(shù)據(jù)
UIBackgroundFetchResultFailed//刷新失敗
通過application的屬性去查應(yīng)用是否開啟后臺(tái)刷新功能backgroundRefreshStatus,返回值
UIBackgroundRefreshStatusRestricted, //< unavailable on this system due to device configuration; the user cannot enable the feature
UIBackgroundRefreshStatusDenied, //< explicitly disabled by the user for this application
UIBackgroundRefreshStatusAvailable //< enabled for this application

在實(shí)際的IOS7環(huán)境中,F(xiàn)etch事件是由系統(tǒng)管理的,app開發(fā)者無法預(yù)先知道Fetch事件達(dá)到的時(shí)機(jī)。但XCode也提供了Fetch事件的調(diào)試辦法,在XCode上運(yùn)行程序后,在Debug->Simulate Background Fetch.
還有一種情況是app沒有運(yùn)行(不在前臺(tái)也不在后臺(tái)),被Fetch事件喚醒執(zhí)行.這種情況的測(cè)試方法如下:
Product->Scheme->Edit scheme 在Debug模式選中Options,點(diǎn)選Launch due to a background fetch event,運(yùn)行即可

具體可以查官方一些文檔

下邊是官方說明
The system guarantees that it will not wake up your application for a background fetch more frequently than the interval provided. Set to UIApplicationBackgroundFetchIntervalMinimum to be woken as frequently as the system desires, or to UIApplicationBackgroundFetchIntervalNever (the default) to never be woken for a background fetch.
This setter will have no effect unless your application has the "fetch" UIBackgroundMode.
See the UIApplicationDelegate methodapplication:performFetchWithCompletionHandler: for more.

Remote notifications

蘋果的APNS(Apple Push Notifications Server)連結(jié)著所有的蘋果可接收推送設(shè)備,如果服務(wù)器想主動(dòng)給應(yīng)用發(fā)送一些消息,必須通過APNS。這里主要記錄一些推送在后臺(tái)如何接收。
在iOS7之前,推送和應(yīng)用完全沒有關(guān)系,設(shè)備收到一條推送消息,應(yīng)用也完全不知道,而且,收到推送之后,如果不是點(diǎn)擊推送消息啟動(dòng)的App,應(yīng)用啟動(dòng)之后,也不會(huì)回調(diào)下邊的方法

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

所以之前,經(jīng)常需要應(yīng)用啟動(dòng)之后,再去后臺(tái)拉取一遍消息,防止有些數(shù)據(jù)沒有正常接收。

之后,可以推送來了之后在后臺(tái)刷新應(yīng)用內(nèi)容,在Background Mode中挑勾Remote notifications,在plist中添加字段App downloads content in response to push notifications,然后在要發(fā)送的數(shù)據(jù)中添加字段content-available:1,否則發(fā)送和普通方式一樣。

Location updates

后臺(tái)定位的應(yīng)用現(xiàn)在也好多,可以在用戶跑步或者騎行的時(shí)候開啟,在后臺(tái)記錄下應(yīng)用跑步的路程。
開啟方法和上邊基本一樣,添加Background Mode,然后在info.plist文件中添加App registers for location updates字段。

_locationManager = [[CLLocationManager alloc ]init];
_locationManager.delegate = self;

_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.allowsBackgroundLocationUpdates=YES;
[_locationManager requestAlwaysAuthorization];

然后,應(yīng)用在進(jìn)入后臺(tái)會(huì)回調(diào)下邊方法更新位置

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容