2010年9月7日 星期二

iPhone Executing Code in the Background (上)

為了徹底搞清楚iOS提供的多工有什麼規範
我居然很認真的看了官方的一些資料,還筆記起來
想說都筆記了,就分享一下,也歡迎大家多多指教
Executing Code in the Background


大部分的程式只要一進入background就會被suspend住而且不執行任何code。
除非我們特別去notify系統,蘋果有提供幾個option讓不同種類的行為在背景下執行。

application準備在background執行
1. application會先link against iOS4 
2. 接著在假定支援多工的情形下會自動implement 合適的method來處理轉換到背景
     的這件事情

application檢查到底有沒有支援多工
首先,程式有背景執行工作的特性不見得都能被iOS的device所支援
又如果,device根本就不支援背景執行工作或不是搭配iOS4及之後的版本,
那系統會用最早先的方式來處理我們的application.
具體來說,當我們的app要離開時,app會被終止並從memory中清掉,然後app的delegate會收到 applicationWillTerminate:的訊息

反正app在不支援多工的情形下應該要有所準備.
如果我們的code想要有支援背景工作但不去執行這部份,
可以用 UIDevice class中 multitaskingSupported的屬性來檢查到底有沒有支援多工.
如果app是要支援iOS4之前的系統那更要在執行背景工作前check這項屬性

Checking for background support on earlier version of iOS
UIDevice* device = [UIDevice currentDevice];
BOOL backgroundSupported = NO;
if ([device respondsToSelector:@selector(isMultitaskingSupported)])
   backgroundSupported = device.multitaskingSupported;

先宣告我們支援哪些背景工作
要支援一些類型的背景工作就必須在app執行前先宣告好.
app使用Info.plist中UIBackgroundModes的鍵值來宣告這類的事情,
這些鍵值的內容是包含了一個或以上的array,例如:

audio: app 可以在背景播放有聲內容.
location: app 可以讓使用者知道自己的所在位置.
voip: app 可以讓使用者使用internet 來打電話.

上述的這些value可以讓app知道什麼時間點該起來回應相對的事件.
然後iOS提供了兩種背景工作的方式

- app 可以要求系統提供一個extra的時間給這項工作
- app 預先排好要被傳遞的local notification時間點

背景狀態轉換的支援
基本上來講只要app是使用iOS4或更新的版本都會支援背景狀態的轉換
如果要很完整的support,或是說用比較嚴謹且正確的方式來支援
則需要確保在delegate中有實作下面幾個methods:

上述這些methods都是在app執行當中即時告知我們app將要轉換狀態了
雖然說有些method早在專案建立之初就已經有實作了,
只是這邊需要增加一些行為判斷來確保背景執行起來是很安全的.
例如: 當一個進入背景並且從記憶體被清除的app重新被launch起來時
我們可能會希望可以繼續之前離開時的狀態.
這個method來檢查有沒有額外的information或是其他已儲存的參數需要在app被喚起後把它restore回app的ui

成為多工感知且可靠的Application
在背景當中執行app一定是比前景中執行要來的限制多多,即使app沒有要在背景執行,
官方也建議了以下的原則:
  • Do not make any OpenGL ES calls from your code.
  • 只要createEAGLContext的物件或是牽涉到任何有關 OpenGL ES的drawing指令會讓app馬上被終止掉.
  • Cancel any Bonjour-related services before being suspended.
  • 當我們的app要移到背景但還沒被suspend之前,應該要在Bonjour那邊取消註冊並且關閉所有與網路服務有關的listing sockets.再說,一個被suspend的程式也不能對incoming 的服務要求有所回應.所以為了避免出現占著茅坑不拉屎的狀況出現,如果不在suspend之前自己關閉所有Bonjour服務,系統還是會自動幫我們關掉的.
  • Be prepared to handle connection failures in your network-based sockets.
  • 系統可能會在一些原因下將socket與我們的app拆開來.只要我們socket-based的程式有為一些類型的網路failure做準備,像是:lost signal或是網路轉換就不會導致任何不正常的問題.當我們要返回程式時使用socket遇到失敗可以很簡單的重新建立連線來解決.
  • Save your application state before moving to the background.
  • 在記憶體不足的情況下,背景執行中的程式會從記憶體中被清掉.被suspend的程式首當其衝,而且系統不會有任何的提示.所以app應該在進入背景執行前要備妥充足的資訊,記錄,參數好讓需要的時候可以重新組回來.在回復app的同時會讓使用者看到app主畫面重啟時的snapshot可以增加一致性.
  • Release any unneeded memory when moving to the background.
  • 當然背景執行的程式需要有充足的狀態訊息來達到快速重返前景執行的目的.但是有物件或是滿大的記憶體空間都沒有要再使用(例如沒用到的圖檔)就應該考慮在進入背景執行前把他們都release掉
  • Stop using shared system resources before being suspended.
  • 如果app有用到系統分享出來的資源(例如AddressBook),要在被suspend之前停止使用.這些系統分享出來的資源優先權會落到前景中的app,如果捨不得放掉這些資源系統還是會強迫中斷的.
  • Avoid updating your windows and views.
  • 雖然說在app背景執行中一直去操縱或是增加window,view object不會導致程式被終止.但是這類的事情應該要延後到app又重回前景再來處理.畢竟在背景的程式是看不到畫面,一直update是update心酸的嗎
  • Respond to connect and disconnect notifications for external accessories.
  • 如果app與外部的附件有communication,系統會自動發出斷線的通知給要進入背景的app.而app應該要註冊這個通知好用來關閉與外部附件的session.當app重回前景時也會藉由註冊的通知來給予重新連線的機會
  • Clean up resources for active alerts when moving to the background.
  • 為了在切換app間保留內文,系統並不會在app進入背景執行時自動關掉action sheet(UIActionSheet)或是alert view(UIAlertView).
  • 但app使用的是iOS 3.x或之前版本, alert view與action sheet仍會被關掉,所以app的cancellation handler就有機會在那邊執行了.這時開發者可以自己決定是要在進入背景執行前提供一個合適的清除行為(手動去cancel那些action sheet或是alert view)還是要把內文資訊給存下來,之後再回復那個view.(萬一在app被終止掉的狀況下)
  • Remove sensitive information from views before moving to the background.
  • 在app要進入背景執行前,系統會給app當下的window做一個快照,當app又要回復時會秀這個快照一下下.因此從applicationDidEnterBackground:這個method回復之前,我們因該針對敏感的使用者私人訊息加以隱藏或覆蓋.
  • Do minimal work while running in the background.
  • 在背景工作能執行的時間要比前景有更多的限制.如果我們的app在背景播放音樂或是在監控location的變化,那就要focus在重點上並把較不重要的事情挪後處理.app若是在背景中花很多時間在執行一些事情,系統會縮短給app的時間甚至通通給終止掉.

還有~等我又發瘋把它們認真看完吧...

    1 則留言:

    內容回應