3 votes

L'application se bloque au niveau de [UIWebView webView:didReceiveTitle:forFrame :].

Je suis en train d'implémenter un simple navigateur in-app. Dans ma vue d'accueil ( UITableViewController ), j'ai quelque chose comme :

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

        WebViewController *webViewController = [[WebViewController alloc] init];
        switch (indexPath.row) {
            case 0:
                webViewController.stringURL = @"http://www.google.com";
                break;
            case 1:
                webViewController.stringURL = @"http://www.bing.com";
                break;
            default:
                webViewController.stringURL = @"http://stackoverflow.com"; 
                break;
        }

        [self.navigationController pushViewController:webViewController animated:YES];
        [webViewController release];
    }

L'application s'est écrasé après avoir fait des allers-retours répétitifs entre ma vue d'accueil et webViewController à plusieurs reprises.

À l'intérieur de WebViewController je n'ai rien d'autre qu'une classe [UIWebView *webView] et un [UIActivityIndicatorView *activityIndicator] . Les deux sont avec des attributs nonatomic, retain . Voici l'implémentation.

        #import "WebViewController.h"
        @implementation WebViewController
        @synthesize webView, activityIndicator, stringURL;

        - (void)dealloc
        {
            [self.webView release];
            self.webView.delegate = nil;
            [self.activityIndicator release]; 
            [super dealloc];
        }

        -(void)loadView {
            UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
            self.view = contentView;    

            CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
            webFrame.origin.y = 0.0f;
            self.webView = [[UIWebView alloc] initWithFrame:webFrame];
            self.webView.backgroundColor = [UIColor blueColor];
            self.webView.scalesPageToFit = YES;
            self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
            self.webView.delegate = self;
            [self.view addSubview: self.webView];
            [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.stringURL]]];

            self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            self.activityIndicator.frame = CGRectMake(0.0, 0.0, 30.0, 30.0);
            self.activityIndicator.center = self.view.center;
            [self.view addSubview: self.activityIndicator];
        }

        - (void)viewDidLoad
        {   
            [super viewDidLoad];
            [self loadView];
        }

        - (void)webViewDidStartLoad:(UIWebView *)webView
        {
            // starting the load, show the activity indicator in the status bar
            [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
            [activityIndicator startAnimating];
        }

        - (void)webViewDidFinishLoad:(UIWebView *)webView
        {
            // finished loading, hide the activity indicator in the status bar
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
            [activityIndicator stopAnimating];
        }

        @end

Je viens de lancer mon application dans Instruments en utilisant le Modèle de zombies qui montre -[UIWebView webView:didReceiveTitle:forFrame:] est l'appel du Zombie. Mais je n'arrive toujours pas à comprendre quel est réellement le problème.

(Veuillez télécharger trace si nécessaire)

Toute aide est grandement appréciée !

[Mise à jour] :

  1. Comme @7KV7 et @David l'ont fait remarquer, il y a un bogue évident dans mes dealloc fonction. Je devrais appeler self.webView.delegate=nil; avant de publier self.webView . Désolé pour cela. Malheureusement, après avoir corrigé le problème, l'application se bloque toujours de la même manière.
  2. Si je supprime [webViewController release]; à partir du premier bloc de code, le crash a disparu. Mais évidemment, il y aura une fuite de mémoire.

3voto

Deepak Danduprolu Points 33605

Tout d'abord, supprimez l'appel à loadView en viewDidLoad . Le framework appellera la méthode lorsqu'il ne trouvera pas de vue fournie dans le fichier XIB. Deuxièmement, votre loadView est rempli de fuites de mémoire. Vous allouez, initialisez et conservez un objet à chaque fois que la méthode est appelée. Vous prenez donc la propriété deux fois et ne la libérez qu'une fois dans le dealloc.

Les objets ne sont pas correctement désalloués. Vous devriez faire quelque chose comme alloc-init-autorelease pour résoudre ce problème. Ensuite, à chaque fois que le contrôleur est chargé, à cause de votre appel à loadView vous finissez par créer deux objets de vue Web et deux demandes. Vous perdez la référence à l'un d'entre eux lorsque vous réaffectez. C'est là que réside le problème mentionné dans le titre. Vous n'êtes pas en mesure de réinitialiser le délégué d'un objet de vue web qui a votre contrôleur comme délégué. Imaginez qu'une requête soit complétée peu après votre départ. Ici, le message ira à un objet zombie. C'est un assez bon exemple pour expliquer pourquoi vous avez besoin de nil de vos délégués.

2voto

7KV7 Points 19750
- (void)dealloc
{
self.webView.delegate = nil;
[self.webView release];
[self.activityIndicator release]; 
[super dealloc];
}

Essayez ceci dealloc . Vous libérez le webview puis de régler le delegate comme nil . Vous devez d'abord définir le delegate comme nil et ensuite release il. J'espère que cela résout le problème.

1voto

skorulis Points 2736

Je pense que ce qui se passe, c'est que vous revenez en arrière alors que la page est encore en train de se charger, ce qui fait que le contrôleur est désalloué et que la vue web finit de se charger. Essayez d'appeler [webView stopLoading] dans votre méthode viewDidUnload pour vous assurer que cela ne se produit pas.

0voto

David Gelhar Points 20703

Je ne sais pas si c'est la cause de votre problème, mais c'est définitivement faux :

[self.webView release];
self.webView.delegate = nil;

Vous ne pouvez pas (sans risque) vous référer à self.webView après l'avoir publié !

0voto

Priyanka Points 152

Au lieu de pousser webViewController, ajoutez sa vue à self.view . Ne pas appeler [self loadView] ; dans viewDidLoad.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X