介紹
這次 iOS7 對程序后台運行進行了加強,但是僅僅是加強而已,要想像 Android 程序那樣自由當然就別想了,蘋果這么做主要還是出於電池使用時間考慮,但是這次的加強對大部分程序基本夠用。
在介紹之前, 我們先回顧一下在 iOS7 之前的后台運行相關的知識。在 iOS7 之前(iOS4 之后)主要有三類的應用程序能夠后台運行:
- 音頻播放
- 后台定位服務
- IP 電話
除了這三種應用,其他程序只能是在進入后台之前向系統請求一個額外的運行時間(最長為 10 分鍾),並在該時間內來進行后台運行操作,如保存用戶信息,上傳或下載數據,進行視頻編碼等操作。
- (void)applicationDidEnterBackground:(UIApplication *)application { static UIBackgroundTaskIdentifier task; task = [application beginBackgroundTaskWithExpirationHandler:^{ task = UIBackgroundTaskInvalid; }; // 執行后台操作 [application endBackgroundTask:task]; }
這次 iOS7 支持了兩種新的程序后台運行模式:
-
需要定期請求數據的程序可以在系統中注冊,這樣程序就可以在后台被定期喚醒來下載新的數據。這種情況需要在程序的 Info.plist 文件中 UIBackgroundModes 項增加 fetch 類型,同時通過 setMinimumBackgroundFetchInterval: 方法來設置程序定期獲取數據的最小時間間隔。你需要實現 application:performFetchWithCompletionHandler: 代理方法並在該方法內執行下載操作。
-
程序還可以通過后台消息推送服務來通知用戶有新的內需可以下載,同時激活后台下載操作。這種需要在 UIBackgroundModes 項中增加 remote-notification 值,同時你需要實現 AppDelegate 方法 application:didReceiveRemoteNotification:fetchCompletionHandler: 來執行你的下載操作。
不管是支持 fetch 或 remote-notification 后台運行模式的程序,都有可能被系統在合適的時候啟動或從后台掛起狀態移除調。在 fetch 模式下,系統會利用有效的信息來決定啟動或激活程序的最佳時期。例如:系統可能會在網絡狀況良好或者設備剛解鎖的時候讓程序執行 fetch 操作。支持 remote-notifiaction 的程序,可以在接收到推送消息的時候被喚醒,但在用戶接收到推送消息之前,程序可以通過定期獲取的形式下載最新內容,並在隨后的推送消息之前就已經准備好將內容展現給用戶。
為了執行后台下載操作,程序應該使用新增的 NSURLSession 類,該類在之前的 NSURLConnectoin 的基礎上提供了更簡潔、基於任務的接口來啟動並執行 NSURLRequest 對象。一個 NSURLSession 對象可以啟動多個下載或上傳任務,並在代理方法里面來處理來自服務器的認證請求。
實現
現在我們來實現 fetch 和 remote-notifiaction 兩種后台運行。
1. 設置
在 Xcode5.0 里面 Capabilities 下可以直接通過勾選的方式選擇應用需要支持的后台運行的類型(可多選哦),我們選中 Background fetch 和 Remote notification 兩項。並在程序的 Info.plist 文件中的 Required background modes 中添加 fetch 和 remote-notification 兩項。
2. Background Fetch
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. [application setMinimumBackgroundFetchInterval: UIApplicationBackgroundFetchIntervalMinimum]; return YES; } - (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ NSURL *url = [NSURL URLWithString:@"http://127.0.0.1:3000/update.do"]; NSURLSession *updateSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [updateSession dataTaskWithHTTPGetRequest:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSDictionary *messageInfo = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSLog(@"messageInfo:%@",messageInfo); completionHandler(UIBackgroundFetchResultNewData); }]; }
首先在 application:didFinishLaunchingWithOptions: 中設置 minimun background fetch interval 類型為 UIApplicationBackgroundFetchIntervalMinimum(默認為 UIApplicationBackgroundFetchIntervalNever),然后實現代理方法 application:performFetchWithCompletionHandler: 中實現數據請求。
為了測試程序后台運行,我們可以新建一個 Scheme,選中 Background Fetch(Launch due to a background fetch event),然后在該 Scheme 下運行程序,程序並不會啟動,但是你能看到它給后台發了請求。
Remote Notifications
類似要實現 remote-notification 模式,需要在原來支持 push 的條件下實現 application:didReceiveRemoteNotification:fetchCompletionHandler: 代理方法,程序在后台收到 payload 中包含 "content-available = 1" 的推送消息時,會執行該代理方法。(因為模擬器無法模擬消息推送,iPad 版本的 iOS7 還沒提供下載,所以我暫時沒法親測)。
總結
總的來說實現上沒有什么太復雜的東西,關鍵是你怎么樣將這兩種新的后台運行模式應用到你的程序中。
Posted by XiaoYi_HD - 6月 23 2013
如需轉載,請注明: 本文來自 Esoft Mobile


