UIWebView is not deallocating memory

2019-02-25 08:34发布

问题:

I'm having some real trouble trying to recover the memory I've allocated for a UIWebView within my application. I essentially create and present the UIWebView temporarily for the user in a separate ViewController, then remove all references and pop the ViewController from the stack. Despite doing all of this, the memory allocated is never returned, and I get stuck with an extra 10 Mb of memory each time I segue to that ViewController again.

Let's see how I'm managing this UIWebView anyways.

Well, for starters, I've got a local reference to it in my header file, show here

#pragma mark UIWebView Properties
/// WebView for loading URL resources
@property (nonatomic, weak)UIWebView *webView;

Notice that it's not an IBOutlet, I'm creating this UIWebView programmatically in the following method, fired in ViewDidAppear.

-(void)presentYoutubeVideoWithID:(NSString *)videoID {
    /* Setup UIWebView */
    UIWebView *webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    /* Set Delegate */
    [webView setDelegate:self];
    /* Set local property */
    [self setWebView:webView];
    /* Add view to ViewController */
    [self.view addSubview:webView];
    /* Set constraints */
    // Removed for simplicity 

    /* Set URL */
    NSString *youTubeVideoHTML = @"<!DOCTYPE html> (Removed) </html>";
    NSString *html = [NSString stringWithFormat:youTubeVideoHTML, self.view.frame.size.width, self.view.frame.size.height, videoID];
    [webView loadHTMLString:html baseURL:[[NSBundle mainBundle]resourceURL]];

    /* Setup Notification */
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleWhenDoneButtonClick:)
                                                 name:UIWindowDidBecomeHiddenNotification
                                               object:nil];
}

And finally, I clean up and "pop" the UIViewController:

-(void)handleWhenDoneButtonClick:(NSNotification *)notification {
    /* Remove Observer */
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIWindowDidBecomeHiddenNotification object:self.view.window];
    /* Remove UIWebView from hierarchy */
    [self.webView removeFromSuperview];
    /* Remove self from webView delegate */
    [self.webView setDelegate:nil];
    /* Remove reference because I can */
    [self setWebView:nil];
    /* Dismiss ViewController */
    [self dismissViewControllerAnimated:YES completion:nil];
}

For a simple enough scenario, nothing seems to actually remove the memory taken up by the UIWebView. As you can see here, the memory usage never decreases:

Before loading the UIWebView:

Once the UIWebView is Open:

After popping the ViewController and removing references to UIWebView:

The amount of memory used here persists indefinitely as far as I can tell. After five minutes, it will still have 34+ Mb allocated. If I open the ViewController again, it will allocate more, and I will end up with about 40 Mb of "base" usage once I pop again.

Leaks: Not being completely dissuaded, I initially went off to look for leaks, thinking I had made some mistake somewhere. However, while I did actually find some very small leaks, they were seemingly entirely related to UIWebView.

Other cases on S.O: I've been looking quite some time for a solution to this on the web, but the only really relevant thread I've found is one from last year as seen here: UIWebView taking lots of memory

It doesn't have an answer yet, and that is probably because (Like most other questions related to this topic), a lot of the replies provide generic/conflicting advice. like suggesting you use ARC (Who doesn't?), or informing OP that they shouldn't keep strong references (Even when they aren't, and the code demonstrates that). Finally, some answers just claim that memory management isn't a problem to begin with because there's enough to go around, and those aren't helpful replies either.

Anyways, this is the current issue I am facing. Thank you for taking the time to read this (If you did!).

回答1:

I have faced the same issue. When pushing a UIViewController with a UIWebView (loading google.com) in an iOS 9 device, the memory size went from 26 MB to 36 MB and it stayed the same after popping the controller.

I did the same test using WKWebView (iOS 8+) instead of UIWebView. This time, the memory size went from 26 MB to ~27.5 MB and it dropped back to ~26 MB after popping the controller.

It seems that the problem is partly due to the way UIWebView is implemented. Maybe you could use https://github.com/floatlearning/FLWebView, which is a WKWebView with UIWebView fallback for iOS.