iOS殺死程序后調用網絡請求和數據庫操作


https://www.jianshu.com/p/56ae5ca5e867

 https://www.imooc.com/wenda/detail/595838

項目中碰到一個需求,就是在退出控制器后進行埋點操作,正常情況我們在controller的delloc中執行埋點的網絡請求就OK了,但是還有一種情況,如果用戶殺死程序,是不會走delloc方法的。這時候需要監聽殺死程序的通知,這里貼下最終代碼,想看思路的請往后看。

- (void)viewDidLoad { [super viewDidLoad]; //監聽通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil]; } //程序被殺死 - (void)applicationWillTerminate:(UIApplication *)application { //進行埋點操作 [self uploadData]; [NSThread sleepForTimeInterval:5]; NSLog(@"程序被殺死"); } 
  • 一開始想着直接在監聽到殺死App后直接埋點,所以在控制器中加入了如下代碼:
- (void)viewDidLoad { [super viewDidLoad]; //監聽通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil]; } //程序被殺死 - (void)applicationWillTerminate:(UIApplication *)application { //進行埋點操作 [self uploadData]; NSLog(@"程序被殺死"); } 
  • 本以為這樣就大功告成了,誰知道埋點沒生效,打斷點發現殺死程序后網絡請求並沒有走完。了解到系統執行完回調applicationWillTerminate:后,在那一次主線程 runloop 結束, 系統就會殺死應用進程, 所以后續的網絡請求,磁盤操作,異步代碼 等等就都沒執行了。在網上查找資料主要有兩種方法:1.說要把這里的網絡請求改成在主線程。2.另外一種方法是阻塞主線程,這里貼下該作者的代碼地址https://www.jianshu.com/p/5142ebe74c6d
  • 看了這兩種方法,覺得第一種方法網絡請求改主線程太過麻煩,因為我這里的埋點有好幾個,所以選擇第二種方法,但覺得作者的做法也太麻煩了,按照思路,無非就是阻塞主線程,讓埋點的網絡請求走完才讓主線程結束,這時候我突然靈機一動:我們啟動APP進入歡迎界面一般就需要沉睡幾秒才進入主界面:
[NSThread sleepForTimeInterval:3]; 

是否可以利用這個方法實現我們的需求?於是我在監聽到App被殺死,進行埋點操作后加入上面的代碼。

- (void)viewDidLoad { [super viewDidLoad]; //監聽通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil]; } //程序被殺死 - (void)applicationWillTerminate:(UIApplication *)application { //進行埋點操作 [self uploadData]; [NSThread sleepForTimeInterval:5]; NSLog(@"程序被殺死"); } 

發現此方法確實可行,而且簡單,但有個缺點就是如果網絡請求慢的話,有可能埋點會失敗。大家可以嘗試用NSTimer阻塞,然后埋點網絡請求完后invalidate。



作者:原味丿丿咖啡Vitas
鏈接:https://www.jianshu.com/p/56ae5ca5e867
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
 
 

applicationWillTerminate什么時候調用,什么時候不調用

iOS
慕仰0522570 2019-10-21 09:47:59

嗨,我已經閱讀了關於applicationWillTerminate被調用和未被調用的幾個問題。

 

我想總結一下我的理解,因為有幾篇文章講的不同。

 

對於IOS(無多任務),總是在按下主頁按鈕時調用它。

 

對於iOS 4及更高版本

 

一種。按下主屏幕按鈕時不會調用它(因為應用程序移至后台)

 

b。當從多任務擴展塢中關閉應用程序時調用該方法,並且如果該應用程序在info.plist中禁用了突然終止標志,則不會調用它。(我設置了“應用程序應獲取App Died事件”,即使在從多任務擴展塢中關閉應用程序時,也沒有調用終止函數)

 

基於此,我有幾個問題

 

設置應用程序應獲取“ App Died”事件標志是一種好習慣嗎?(我設置了“應用程序應獲取App Died事件”,即使在從多任務擴展塢中關閉應用程序時,也沒有調用終止函數)

 

要么

 

與“ info.plist”設置相比,注冊“ UIApplicationWillTerminateNotification”更好嗎?

 

基本上,我只需要在應用終止時才需要做一些工作,而不必在它移到后台時才需要做。

 

要么

 

編輯(1):應用終止后,以下內容將發送到該應用。我怎么抓到它?

 

程序收到信號:“ SIGKILL”。

 

編輯(2):

 

請注意:從多任務擴展塢中卸下時,它在IOS 4及更高版本中不會被調用。您可能以為是。但就我而言,事實並非如此。

 

我問是否有人知道為什么?還有其他我想念的東西嗎?

 

另請注意,我設置了“應用程序應獲取應用程序死亡事件”,即使這樣它也沒有被調用。

有人面臨與我類似的問題嗎?

 

查看完整描述

3 回答

?
慕勒3428872

簡而言之,除非您UIApplicationExitsOnSuspend在Info.plist中將其設置為YES ,否則在iOS4及更高版本中,無法保證applicationWillTerminate:會被調用。

 

如文檔所述:

 

對於支持后台執行的應用程序,當用戶退出應用程序時通常不會調用此方法,因為在這種情況下,應用程序只是移至后台。然而,這種方法可以在其中應用程序在背景中(未暫停)運行情況被調用,該系統需要終止它由於某種原因

 

(強調我的。)

 

如果您需要在應用退出之前執行某些操作,則需要在中執行操作applicationDidEnterBackground:。無法捕捉SIGKILL。

 

 反對 回復2019-10-21
 
?
倚天杖

據我所知,您的應用程序將在3種情況下死亡。

  1. 在最終用戶終止后,您可以在中做某事-[UIApplication applicationWillEnterBackground:],在這種情況下,-[UIApplication applicationWillTerminate:]將不會調用。

  2. 被系統丟棄,例如內存不足,您可以在中做某事-[UIApplication applicationWillTerminate:],在這種情況下,我們不知道是否applicationWillEnterBackground:已被調用;

  3. 崩潰了,只能使用某種崩潰報告工具來完成。(編輯:捕捉SIGKILL是不可能的)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM