【问题标题】:iOS App Crashes - I suspect it has to do with UIWebView using WebSocketsiOS 应用程序崩溃 - 我怀疑它与使用 WebSockets 的 UIWebView 有关
【发布时间】:2014-01-05 07:16:05
【问题描述】:

我目前没有使用 applicationWillResignActive / applicationWillEnterForeground 或任何类似的东西,因为我不确定如何处理我遇到的这个问题。

如果我打开我的应用程序,它会一直崩溃,按主屏幕,等待大约 5 分钟,然后尝试再次进入应用程序。

该应用程序主要是一个加载 node.js 驱动的 websocket 的 UIWebView,所以我认为这是罪魁祸首。

当用户离开应用程序时,如何阻止 UIWebView 执行任何操作/所有操作(我猜想需要使用 applicationWillResignActive)。我已经尝试了六个想法,但我终其一生都无法让应用停止崩溃。

我目前的想法:

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

...然后从那里我编辑我的 ViewController.m 文件以对该页面上的 UIWebView 执行某些操作。问题是,什么会阻止 UIWebView 在后台执行任何操作?我试过停止加载,但由于某种原因没有成功,或者它仍然会崩溃。

【问题讨论】:

  • 您是否正在自定义 NSUrlProtocol?并在您的 webView 控制器中做一些类似 registerClass 的事情?发布您的崩溃日志或网络视图代码。
  • 你能找到你的应用崩溃的原因吗?
  • 显示崩溃的堆栈跟踪。

标签: ios iphone objective-c uiwebview websocket


【解决方案1】:

我无法重现确切的问题(WebThread: EXC_BAD_ACCESS (code=1, address=0x5)——取自您的other question),但我确实注意到 WebSocket 消息正在被缓冲,所以如果您将应用程序留在后台足够长的时间,可能,您将遇到可能导致此崩溃的内存压力问题。

但是,在研究这个问题的过程中,我确实设法使应用程序可靠地崩溃,并使用源自 WebThreadEXC_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 连接发送。

【讨论】:

  • 很好的答案@neilco。一个建议,你能不能只在 Javascript 中使用暂停/恢复事件?它们应该很好地转化为 appWillResignActive/appDidBecomeActive。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多