1、IOS允許App的一個(gè)Socket在App切換到后臺(tái)后仍然保持連接. 這樣,當(dāng)有通話請(qǐng)求的時(shí)候,App能及時(shí)處理. 這個(gè)socket需要在應(yīng)用第一次啟動(dòng)的時(shí)候創(chuàng)建, 并標(biāo)記為"此socket用于VoIP服務(wù)". 這樣當(dāng)App切換到后臺(tái)的時(shí)候,IOS會(huì)接管這個(gè)標(biāo)記為"用于VoIP服務(wù)"的socket. 這個(gè)socket的響應(yīng)函數(shù)(比如,一個(gè)delegate,或者是個(gè)block)會(huì)正常的響應(yīng), 就像App還在前臺(tái)一樣.
2、10s魔咒. 當(dāng)socket有任何數(shù)據(jù)從服務(wù)端傳來(lái), 你在app里為socket寫的響應(yīng)函數(shù)都會(huì)做處理.但是, 你只有最多10s的時(shí)間來(lái)干你想干的事情. 也就意味著你在響應(yīng)函數(shù)里新建一個(gè)大于10s的timer是沒(méi)有意義的. 并且IOS并不保證給你足夠10s的時(shí)間,視系統(tǒng)情況而定.
3某抓、在socket的響應(yīng)函數(shù)里, 你能通過(guò)NSLocalNotification來(lái)通知用戶"電話來(lái)了". 除此之外, 你沒(méi)法做其他任何視覺上的動(dòng)作來(lái)提醒用戶, 因?yàn)槟愕腶pp還處于某個(gè)不知道的次元, 甚至連window都還沒(méi)創(chuàng)建.
4、你永遠(yuǎn)也沒(méi)有辦法知道或者決定NSLocalNotification的樣式是banner還是alert. 你也許鐘愛后者, 但是決定權(quán)在用戶手里.
5州藕、允許在后臺(tái)定期執(zhí)行一段代碼. 你可以設(shè)定一個(gè)大于等于10分鐘的時(shí)間t, 和一個(gè)定期執(zhí)行的handler, IOS系統(tǒng)會(huì)在每次經(jīng)過(guò)t時(shí)間的時(shí)候調(diào)用一次這個(gè)handler. 但是IOS不保證這個(gè)handler會(huì)準(zhǔn)時(shí)運(yùn)行, 只保證在時(shí)間t范圍內(nèi)的某個(gè)點(diǎn)會(huì)執(zhí)行一次.
6换棚、我們通常用樓上的handler處理socket的斷線重連操作. 因?yàn)榫W(wǎng)絡(luò)不穩(wěn)定, 或者用戶開啟飛行模式等原因, 我們用于voip服務(wù)的socket會(huì)斷開連接. 在這個(gè)handler里,如果發(fā)現(xiàn)連接斷開,我們只需要跟條目1一樣的創(chuàng)建socket,設(shè)置一樣的socket響應(yīng)函數(shù),一切又會(huì)恢復(fù)正常.
7浓领、不建議這個(gè)handler做太多事情, 因?yàn)樗灿?0s魔咒.(據(jù)不完全統(tǒng)計(jì),蘋果所有的后臺(tái)處理都有這個(gè)10s限制. 不保證絕對(duì)正確哈, 僅供參考)
8、自啟服務(wù). 當(dāng)IOS重新啟動(dòng), 或者你的app因?yàn)槠渌蛲顺鰰r(shí), IOS會(huì)馬上啟動(dòng)你注冊(cè)為voip的app, 你可以很迅速的恢復(fù)socket連接. 但是, 從底部多任務(wù)欄中手動(dòng)關(guān)閉應(yīng)用除外.更"code"的說(shuō)明是:當(dāng)程序退出的exitcode != 0,IOS會(huì)重啟你的app.經(jīng)試驗(yàn)發(fā)現(xiàn),從底部多任務(wù)欄關(guān)閉的時(shí)候,程序的exitcode == 0.
9苦丁、如果你親愛的用戶是一個(gè)典型的"app終結(jié)者",那么你還剩最后一條路來(lái)通知來(lái)電提醒:NSRemoteNotification. 你也許會(huì)被NSRemoteNotification的可靠性和實(shí)時(shí)性折騰的抓狂, 但是, 誰(shuí)讓你選了IOS? 你享受了封閉帶來(lái)的傳世體驗(yàn), 也得承受封閉的限制.
10浸颓、當(dāng)條目8描述的情況發(fā)生之后,app的application:didFinishLaunchingWithOptions:會(huì)被調(diào)用. 但是,請(qǐng)時(shí)刻提醒自己我們的app仍然處于后臺(tái). 我們以前總在這里創(chuàng)建window創(chuàng)建rootController, 但現(xiàn)在不必了. 現(xiàn)在我們需要的就是把可愛的socket連上, 像在條目1里一樣,讓一切回歸正常(我不去寫歌詞真浪費(fèi)了_).
11、在application:didFinishLaunchingWithOptions:里你能通過(guò)[application applicationState] == UIApplicationStateBackground來(lái)判斷是正常啟動(dòng)應(yīng)用還是系統(tǒng)自動(dòng)啟動(dòng), 然后決定該創(chuàng)建window還是創(chuàng)建voip的socket.