UIWebView not freeing all live bytes using ARC

北城以北 提交于 2019-12-03 12:39:25

I had the same-ish problem, the i found this little piece of magic

/*

 There are several theories and rumors about UIWebView memory leaks, and how
 to properly handle cleaning a UIWebView instance up before deallocation. This
 method implements several of those recommendations.

 #1: Various developers believe UIWebView may not properly throw away child
 objects & views without forcing the UIWebView to load empty content before
 dealloc.

 Source: http://stackoverflow.com/questions/648396/does-uiwebview-leak-memory

 */        
[webView loadHTMLString:@"" baseURL:nil];

/*

 #2: Others claim that UIWebView's will leak if they are loading content
 during dealloc.

 Source: http://stackoverflow.com/questions/6124020/uiwebview-leaking

 */
[webView stopLoading];

/*

 #3: Apple recommends setting the delegate to nil before deallocation:
 "Important: Before releasing an instance of UIWebView for which you have set
 a delegate, you must first set the UIWebView delegate property to nil before
 disposing of the UIWebView instance. This can be done, for example, in the
 dealloc method where you dispose of the UIWebView."

 Source: UIWebViewDelegate class reference    

 */
[webView setDelegate:nil];


/*

 #4: If you're creating multiple child views for any given view, and you're
 trying to deallocate an old child, that child is pointed to by the parent
 view, and won't actually deallocate until that parent view dissapears. This
 call below ensures that you are not creating many child views that will hang
 around until the parent view is deallocated.
 */

[webView removeFromSuperview];

I have been using ARC for a while now and I have found in the past that the web view will hold onto whatever was loaded until its told to load something else. The way I get around this is to use a javascript call in the view will (or Did) dissapear method like so:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.webView loadHTMLString:@"<html></html>" baseURL:nil];
}

This releases the memory for me.

UIWebView is a memory pig and doesn't deallocate memory well. I put a -(void) dealloc call in your CustomWebView class and it's called as expected when the Back button is hit.

You can try [[NSURLCache sharedURLCache] removeAllCachedResponses] or use and then free your own copy of NSURLCache, but frankly UIWebView never fully cleans up after itself.

I havent used ARC yet, but looking at your custom webview code, I think your webviews that you created are still alive.

if you want to be sure that your webviews are killed properly, make sure that in the viewWill/DidDisappear, call [webview stopLoading], and nil the webview.

(caution: if you are pushing another view, then also the webview will be killd, so make sure to handle those issues well)

Most often, I have had issues with webViews where even after popping the viewController, a call back to some webView delegate method would crash the app. (I guess ARC prevents it from crashing).

Let me know if this helps.

Brendan a couple of points:

You have not posted enough code to be sure of what is happening. But why not have the controller own a SINGLE UIWebView and rather than creating another one on each button press simply pass it a string with the relevant URL? That is a better design pattern that will guarantee that you never have more than one around.

@interface WebViewViewController : UIViewController<UIWebViewDelegate>

- (void)viewDidLoad
{
[super viewDidLoad];
NSString* urlAddress = @"http://www.google.com";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
self.webView.delegate = self;
[self.webView loadRequest:requestObj];
}

-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[_webView stopLoading];
[_webView loadHTMLString:@"<html><head></head><body></body></html>" baseURL:nil];
[_webView stopLoading];
[_webView removeFromSuperview];
}

- (void)dealloc
{
[_webView stopLoading];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
[_webView stopLoading];
_webView = nil;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!