2014-01-05 43 views
5

我目前沒有使用applicationWillResignActive/applicationWillEnterForeground或類似的東西,因爲我不確定如何處理我遇到的這個問題。iOS應用程序崩潰 - 我懷疑它與使用WebSockets的UIWebView有關

我的應用程序不斷崩潰,如果我打開它,按主屏幕,等待大約5分鐘,並嘗試再次回到應用程序。

該應用程序主要是一個UIWebView,加載一個node.js供電的websocket,所以我認爲這是罪魁禍首。

當用戶離開應用程序(applicationWillResignActive是我猜測需要使用的)時,如何停止UIWebView做任何事情/所有事情。我玩過半打的想法,我不能讓我的生活讓應用停止崩潰。

我目前的想法:

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
[[NSNotificationCenter defaulCenter] postNotificationName:@"EnterBackground" object:Nil userInfo: Nil]; 
} 

...,然後從那裏修改我ViewController.m文件做一些事來了一個UIWebView在該網頁。問題是,什麼會阻止UIWebView在後臺執行任何操作?我試過停止加載,出於某種原因沒有成功,否則它會崩潰。

+1

你是否在自定義NSUrlProtocol?並在你的webView控制器中做一些像registerClass的事情?發佈您的崩潰日誌或網頁瀏覽代碼。 – johnMa

+0

你能找到你的應用崩潰的原因嗎? – sunkehappy

+2

顯示崩潰的堆棧跟蹤。 –

回答

6

我無法複製確切的問題(WebThread: EXC_BAD_ACCESS (code=1, address=0x5) - 從您的other question中獲取),但我確實注意到WebSocket消息正在被緩衝,所以如果您將應用程序保留在背景中足夠長的時間,遇到可能導致此次事故的內存壓力問題。

然而,在研究這個問題的過程中,我還是設法使應用程序可靠地從WebThread一個EXC_BAD_ACCESS發起崩潰,所以我會在這裏發表的細節,希望它可能使用到您或他人。

就這個問題而言,我的WebSocket服務器只是每秒向任何連接的客戶端廣播時間。

正如我所提到的,我注意到當應用程序背景時UIWebView正在緩衝WebSocket消息。爲了防止這種情況發生,我想在應用程序移入後臺時關閉WebSocket連接。

在我主持的UIWebView的視圖控制器,我註冊了一個選擇爲UIApplicationWillResignActiveNotification並在這選擇,我打電話給我的網頁中的JavaScript函數,WebSocket的對象上調用close

ViewController.m:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(appWillResignActive:) 
               name:UIApplicationWillResignActiveNotification 
               object:nil]; 
} 

- (void)appWillResignActive:(NSNotification *)notification 
{ 
    [self.webView stringByEvaluatingJavaScriptFromString:@"closeWebSocket();"]; 
} 

網頁:

function closeWebSocket() { 
    socket.close(); // socket is an instance of WebSocket 
    socket = undefined; 
} 

我想WebSocket的重新連接,當應用程序被移回前臺,所以我註冊了另一種選擇,這次是UIApplicationDidBecomeActiveNotification,並在該選擇器中調用另一個函數來初始化WebSocket連接。

ViewController。L:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(appWillResignActive:) 
               name:UIApplicationWillResignActiveNotification 
               object:nil]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(appDidBecomeActive:) 
               name:UIApplicationDidBecomeActiveNotification 
               object:nil]; 
} 

- (void)appWillResignActive:(NSNotification *)notification 
{ 
    [self.webView stringByEvaluatingJavaScriptFromString:@"closeWebSocket();"]; 
} 

- (void)appDidBecomeActive:(NSNotification *)notification 
{ 
    [self.webView stringByEvaluatingJavaScriptFromString:@"openWebSocket();"]; 
} 

網頁:

function openWebSocket() { 
    socket = new WebSocket("ws://" + document.location.host + "/ping"); 

    socket.onopen = function() { console.log("Opened"); }; 
    socket.onmessage = function (message) { 
     var log = $('#log'); 
     log.html(message.data + '<br>' + log.html()); 
     console.log(message.data); 
    }; 
    socket.onclose = function() { console.log("Closed"); }; 
} 

運行應用程序時,WebSocket連接建立,收到的消息,以及應用程序移動到後臺。幾秒鐘後,我將應用程序帶回前臺(通過點擊應用程序圖標),應用程序崩潰,類似於WebThread: EXC_BAD_ACCESS (code=1, address=0x5的異常。造成這種情況的原因是當應用程序被帶回到前臺時,對openWebSocket()的JavaScript調用的評估。延遲執行openWebSocket()幾毫秒解決了問題。通過appDidBecomeActive方法結束這樣看:

- (void)appDidBecomeActive:(NSNotification *)notification 
{ 
    [self.webView stringByEvaluatingJavaScriptFromString:@"setTimeout(openWebSocket, 5);"]; 
} 

再次運行應用程序時,WebSocket連接建立,接收到的消息,和應用程序背景執行。幾秒鐘後,當我將應用程序帶回前臺時,應用程序沒有崩潰,並且消息通過WebSocket連接再次開始。

+0

好的回答@neilco。一個建議,你可以不使用JavaScript中的暫停/恢復事件嗎?他們應該很好地翻譯appWillResignActive/appDidBecomeActive。 – Marko