我无法重现确切的问题(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.m:
- (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 连接发送。