29

我遇到使用 UIWebView 的应用程序崩溃。通常是在页面没有完全加载并且 UIWebView 被发送 stopLoading 选择器的时候。或者当 UIWebView 完全加载页面时。我有EXC_BAD_ACCESS。堆栈看起来像这样:

#0  0x95bb7688 in objc_msgSend
#1  0x30a671db in -[UIWebView webView:decidePolicyForNavigationAction:request:frame:decisionListener:]
#2  0x3024a10d in __invoking___
#3  0x30249ff8 in -[NSInvocation invoke]
#4  0x358ab160 in HandleDelegateSource
#5  0x302452c1 in CFRunLoopRunSpecific
#6  0x30244628 in CFRunLoopRunInMode
#7  0x32044c31 in GSEventRunModal
#8  0x32044cf6 in GSEventRun
#9  0x309021ee in UIApplicationMain
#10 0x0000239c in main at main.m:13

对我来说最奇怪的是webView:decidePolicyForNavigationAction:request:frame:decisionListener:发送到 UIWebView 的选择器,因为 UIWebView 文档中没有这样的选择器!仅适用于 Cocoa(不是 cocoa touch)WebView。我怀疑 UIWebView 或其委托有问题。但我无法设置断点来观看它们。请告知我如何在这种情况下获得更多信息。

4

6 回答 6

87

在离开视图之前,您必须停止加载 webView 并删除委托:

// ARC (correct solution)
- (void)dealloc {
    [_webView setDelegate:nil];
    [_webView stopLoading];
}

// non ARC
- (void)dealloc {
    [webView setDelegate:nil];
    [webView stopLoading];
    [webView release];
    [super dealloc];
}

// ARC (older solution)
- (void)viewWillUnload {
    [webView setDelegate:nil];
    [webView stopLoading];
}

Apple 文档所说的内容: 重要在发布您已为其设置委托的 UIWebView 实例之前,您必须首先将其委托属性设置为 nil。例如,这可以在您的 dealloc 方法中完成。

于 2009-11-13T10:54:23.450 回答
9

尝试打开 NSZombie,看看是否有什么东西发布得太早了。

可能是您取消了视图的加载,然后立即拆除了您的视图层次结构,导致在 UIWebView 搞砸之前释放了一些东西。

在这种情况下,回溯看起来很明显就像是一个提前释放的委托。委托关系通常很弱,并且缺乏 GC,是悬挂引用的绝佳来源,导致看起来像这样的崩溃。

于 2009-08-31T20:51:28.407 回答
5

View Will Disappear 是已接受答案的一个可行选项:

// ARC
- (void)viewWillDisappear:(BOOL)animated{
    [self.webView setDelegate:nil];
    [self.webView stopLoading];
}

这完美适用于 iOS 6。

于 2013-05-20T20:13:49.917 回答
2

我在滚动的 UIWebView 上遇到了 EXC_BAD_ACCESS 崩溃,但仅在 iPad 上,并且仅当用户在关闭包含它的视图控制器时离开 UIWebView 滚动时。

将代理设置为 nil 并不能解决我的问题,但我在其他问题下找到了解决方案。我将此代码添加到我的关闭按钮调用的方法中:

for (id subview in webView.subviews){
        if ([[subview class] isSubclassOfClass: [UIScrollView class]]){
            [subview setContentOffset:CGPointZero animated:NO];
        }
    }

这会在调用 dealloc 方法之前停止滚动,这似乎是问题所在。

于 2012-03-27T16:30:21.157 回答
1

我也看到了这个确切的错误,它是由我指定给未保留的 UIWebView 的委托(在我的情况下为 UIViewController)引起的。

于 2012-01-21T21:15:06.560 回答
0

最好从 ViewController 的 dealloc 方法处理从 webview 取消注册委托和停止 webview 加载。

作为 viewWillDisappear 可能失败的示例:如果 ViewController 是另一个 ViewController 的子项,则可以使用动画触发从父 ViewController 的视图中删除 ViewController 的视图。同时,您可以将 ViewController 从其父级中移除并取消其引用。此时 ViewController 将为 nil,并且永远不会调用 viewWillDisappear,这意味着永远不会清理 WebView 委托。

使用 dealloc 并确保您的 WebView 始终被清理。

于 2013-08-19T11:52:48.010 回答