I'm experiencing crashes of an app that uses UIWebView. Usually it's when page is not fully loaded and UIWebView is sent stopLoading selector. Or when UIWebView fully loaded page. I've got EXC_BAD_ACCESS
. Stack looks like this:
#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
for me most strange thing here is webView:decidePolicyForNavigationAction:request:frame:decisionListener:
selector sent to UIWebView, because there is no such selector in UIWebView documentation! Only for Cocoa (not cocoa touch) WebView.
I suspect that there is something wrong with UIWebView or its delegate. But I can't set breakpoint to watch them. Please advise how I can get more info in this situation.
Apple is phasing out UIWebView, which is used by developers for integrating web content into an app in a quick and secure manner. Apple is replacing UIWebView (and WebView) with WKWebView, an updated version, as UIWebView has been deprecated.
Android is powered by Chrome. Mobile Safari UIWebView. The UIWebView is different from the ordinary Safari browser, as it is not a stand-alone browser, but merely browser functionality that is embedded in a third party app that allows the app to display content from the web.
Difference Between UIWebview and WKWebViewUIWebview is a part of UIKit, so it is available to your apps as standard. You don't need to import anything, it will we there by default. But WKWebView is run in a separate process to your app,. You need to import Webkit to use WKWebView in your app.
New apps containing these frameworks are no longer accepted by the App Store. And last year, we announced that the App Store will no longer accept app updates containing UIWebView as of December 2020.
You have to stop loading the webView and remove the delegate before leaving the view:
// 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];
}
What Apple documentation is saying: Important Before releasing an instance of UIWebView for which you have set a delegate, you must first set its delegate property to nil. This can be done, for example, in your dealloc method.
Try turning on NSZombie and see if something is being released too soon.
It may be that you are canceling the loading of the view and then immediately tearing down your view hierarchy, causing something to be released before the UIWebView is done messing with it.
In this case, the backtrace looks distinctly like it is a delegate that is being released early. Delegate relationships are typically weak and, lacking GC, are a wonderful source for dangling references that causes crashes that look just like this.
View Will Disappear is an working option to the accepted answer:
// ARC
- (void)viewWillDisappear:(BOOL)animated{
[self.webView setDelegate:nil];
[self.webView stopLoading];
}
This works for iOS 6 perfectly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With