How to safely shut down a loading UIWebView in viewWillDisappear?

前端 未结 6 1213
温柔的废话
温柔的废话 2020-12-07 11:34

I have a view containing a UIWebView which is loading a google map (so lots of javascript etc). The problem I have is that if the user hits the \'back\' button on the nav ba

相关标签:
6条回答
  • 2020-12-07 11:51

    Possibly related, I sometimes (again totally intermittent) get an ugly heisenbug where clicking the back button on some other view's navbar will pop the title, but not the view. In other words I get left with the title of view n on the stack, but the view showing is still view n+1 (the result is you're trapped on this screen and cannot get back to the root view - you can go the other direction, i.e. push more views and pop back to the view that didn't pop corrrectly, just not to the root view. The only way out is to quit the app). At other times the same sequence of pushes and pops on the same views works fine.

    I have the same problem, when I'm use navigation controller with view controllers in stack > 2 and current view controller index > 2, if an memoryWarning occurs in this momens, it raises the same problems.

    There is inly 1 solution, which I found after many experiments with overriding pop and push methods in NavigationController, with the stack of view controllers, with views and superviews for stacked ViewControllers, etc.

    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    
    @interface FixedNavigationController : 
    UINavigationController <UINavigationControllerDelegate>{
    
    }
    
    @end
    

    #import "FixedNavigationController.h"
    
    static BOOL bugDetected = NO;
    
    @implementation FixedNavigationController
    
    - (void)viewDidLoad{
        [self setDelegate:self];
    }
    
    - (void)didReceiveMemoryWarning{
        // FIX navigationController & memory warning bug
        if([self.viewControllers count] > 2)
            bugDetected = YES;
    }
    
    - (void)navigationController:(UINavigationController *)navigationController 
    didShowViewController:(UIViewController *)viewController 
    animated:(BOOL)animated
    {
    
        // FIX navigationController & memory warning bug
        if(bugDetected){
            bugDetected = NO;
    
            if(viewController == [self.viewControllers objectAtIndex:1]){
                [self popToRootViewControllerAnimated:NO];
                self.viewControllers = [self.viewControllers arrayByAddingObject:viewController];
            }
        }
    }
    
    @end
    

    It works fine for 3 view controllers in stack.

    0 讨论(0)
  • 2020-12-07 11:53

    I had a similar problem to this using a UIWebView in OS3 - this description was a good starting point, however I found than simply nil'ing out the web view delegate before releasing the webView solved my problem.

    Reading the sample code (the accepted answer - above) - it seems like a lot of overkill. E.g. [webView release] and webView = nil lines do exactly the same thing given the way the author describes the variable is declared (so you don't need both). I'm also not fully convinced by all the retain and release lines either - but I guess your mileage will vary.

    0 讨论(0)
  • 2020-12-07 11:57

    There's a few ways to handle it, but this should work. You want the didFailLoadWithError message, it's what tells you it's stopped.

    Set a flag isLeaving=YES; Send the Webview a stopLoading.

    In didFailLoadWithError:, check for the error you get when the webview stops:

    if ((thiserror.code == NSURLErrorCancelled) && (isLeaving==YES)) {

    [otherClass performSelector:@selector(shootWebview) withObject:nil withDelay:0]

    }

    release the webView in shootWebview:


    variations: if you want to be cavalier about it, you can do the performSelector:withObject:withDelay: with a delay of [fillintheblank], call it 10-30 seconds without the check and you'll almost certainly get away with it, though I don't recommend it.

    You can have the didFailLoadWithError set a flag and clean it up somewhere else.

    or my favorite, maybe you don't need to dealloc it all when you leave. Won't you ever display that view container again? why not keep it around reuse it?

    Your debug being different from release issue, you might want to check your configuration to make sure that it's exactly the same. Bounty was on the reproducible part of the question, right? ;-).

    -- Oh wait a second, you might be taking a whole View container down with the WebView. You can do a variation on the above and wait to release the whole container in shootWebView.

    0 讨论(0)
  • 2020-12-07 12:04

    The UINavigationController bug you're describing in the second part of your post might be related to your handling of memory warnings. I've experienced this phenomenon and I"ve been able to reproduce it on view n in the stack by simulating a memory warning while viewing view (n+1) in the stack.

    UIWebView is a memory eater, so getting memory warnings wouldn't be surprising when it's used as part of a view hierarchy.

    0 讨论(0)
  • 2020-12-07 12:07

    A variation on this should fix both the leaking and zombie issues:

    - (void)loadRequest:(NSURLRequest *)request
    {
        [self retain];
        if ([webView isLoading])
            [webView stopLoading];
        [webView loadRequest:request];
        [self release];
    }
    - (void)webViewDidStartLoad:(UIWebView *)webView
    {
        [self retain];
    }
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        [self release];
    }
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
    {
        [self release];
    }
    
    - (void)viewWillDisappear
    {
        if ([webView isLoading])
            [webView stopLoading];
    }
    
    - (void)dealloc
    {
        [webView setDelegate:nil];
        [webView release];
        [super dealloc];
    }
    
    0 讨论(0)
  • 2020-12-07 12:15

    A simple release message in dealloc ought to be enough.

    Your second problem sounds like a prematurely deallocated view, but I can't say much without seeing some code.

    0 讨论(0)
提交回复
热议问题