2013-04-26 2 views
2

En utilisant un UIWebView dans mon application et je ne peux pas sembler libérer la mémoire qu'il utilise. J'ai un UIButton qui charge un contrôleur de vue qui contient le UIWebView. Lorsque la WebView est chargée, la mémoire réelle (en la vérifiant à l'aide d'Instruments) augmente mais ne diminue pas après mes tentatives pour la libérer.monotouch disposer UIWebView

Lorsque le bouton est pressé:

si (childBroswer = null!)

 { 
      childBroswer.Dispose(); 
      childBroswer = null; 
     } 

     childBroswer = new ChildBrowser(url); 

     AppDelegate d = (AppDelegate)UIApplication.SharedApplication.Delegate; 

     if (d.rootNavigationController.RespondsToSelector(
      new MonoTouch.ObjCRuntime.Selector("presentViewController:animated:completion:"))) 
     { 
       d.rootNavigationController.PresentViewController(childBroswer, true, null); 
     } 
     else 
     { 
      d.rootNavigationController.PresentModalViewController(childBroswer, true); 
     } 

classe navigateur enfant:

public partial class ChildBrowser : UIViewController 
{ 
    public string _url {get;set;} 
    UIActivityIndicatorView activityIndicator; 
    UIWebView webBrowser; 
    NSUrl nsURL; 
    NSUrlRequest nsURLRequest; 
public ChildBrowser (string url) : base ("ChildBrowser", null) 
    { 
     nsURL = new NSUrl(url); 
     nsURLRequest = new NSUrlRequest(nsURL); 
    } 

    public override void DidReceiveMemoryWarning() 
    { 
     // Releases the view if it doesn't have a superview. 
     base.DidReceiveMemoryWarning(); 

     // Release any cached data, images, etc that aren't in use. 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 

     if (webBrowser == null) 
     { 
      webBrowser = new UIWebView(new RectangleF(0,41,320,380)); 
     } 

     this.Add(webBrowser); 

     webBrowser.LoadFinished += (object sender, EventArgs e) => { 
      activityIndicator.StopAnimating(); 
     } ; 

     webBrowser.LoadStarted += (object sender, EventArgs e) => { 

      if (activityIndicator == null) 
      { 
       activityIndicator = new UIActivityIndicatorView(new RectangleF(UIScreen.MainScreen.Bounds.Width/2 - 50, 
                       UIScreen.MainScreen.Bounds.Height/2 - 30,100,100)); 
       activityIndicator.Color = UIColor.Black; 
      } 

      activityIndicator.StartAnimating(); 
      this.Add(activityIndicator); 
     } ; 

     webBrowser.LoadHtmlString("<html><head></head><body></body></html>",null); //stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML = \"\";"]; 
     webBrowser.LoadRequest(nsURLRequest); 

     closeBrowser.TouchUpInside += handleClose; 


     // Perform any additional setup after loading the view, typically from a nib. 
    } 

    private void handleClose(object sender, EventArgs e) 
    { 
     webBrowser.Delegate = null; 
     webBrowser.StopLoading(); 
     webBrowser.Dispose(); 

     DismissViewController(true,delegate { 
      closeBrowser.TouchUpInside -= handleClose; 
      webBrowser.RemoveFromSuperview(); 
      this.Dispose(); 
     }); 
    } 

    public override void ViewWillAppear (bool animated) 
    { 
     base.ViewWillAppear (animated); 


    } 

    public override void ViewDidDisappear(bool animated) 
    { 
     base.ViewDidDisappear(true); 
     //webBrowser.RemoveFromSuperview(); 
    } 

    public void webViewDidFinishLoad(UIWebView webView) 
    { 
     //string u = ""; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     ReleaseDesignerOutlets(); 
     base.Dispose(disposing); 
    } 

Que manque-t-il?

Merci!

Répondre

3

La mémoire pour native objets n'est pas récupérée lorsque vous appelez Dispose. L'appel Dispose ne supprime que la référence gérée - mais le runtime ObjC (référence comptée) ne libérera pas l'objet tant qu'il n'y aura pas de référence native. Voir ce Q&A pour plus de détails ...

Cela signifie que le code tel que:

this.Add(webBrowser); 

va créer une telle référence native et il est probable (si non sectionnées ailleurs) pour garder le webBrowser exemple vivant tant que this est vivant. Si vous gardez Add alors votre consommation de mémoire ne cessera de croître.

+1

Merci. N'est-ce pas censé le libérer? DismissViewController (true, délégué { closeBrowser.TouchUpInside - = handleClose; this.Dispose(); }); –

+0

Ne peut pas dire sans voir toute la source. 'this.Dispose' ne relèvera (encore) que la référence managée à' this', donc si quelque chose d'autre (natif) a une référence à 'this', alors il restera vivant (et gardera votre' UIWebView' en vie aussi). – poupou

+1

J'ai modifié la question pour inclure la classe du navigateur enfant. J'espère que ça aide, car cela cause beaucoup de problèmes à mon application ... 10X! –

2

Je suis l'OP - Il semble que libérer l'utilisation de la mémoire de UIWebView est assez difficile, même en Objective-C.

Ce que j'ai finalement fait, ce qui ne résout pas le problème, mais l'amélioration de la libération de la mémoire ajoute les lignes suivantes lors de la fermeture du UIWebView:

NSUrlCache.SharedCache.RemoveAllCachedResponses();

 NSUrlCache.SharedCache.DiskCapacity = 0; 

     NSUrlCache.SharedCache.MemoryCapacity = 0; 

     webView.LoadHtmlString("",null); 

     webView.EvaluateJavascript("var body=document.getElementsByTagName('body')[0];body.style.backgroundColor=(body.style.backgroundColor=='')?'white':'';"); 

     webView.EvaluateJavascript("document.open();document.close()"); 

     webView.StopLoading(); 

     webView.Delegate = null; 

     webView.RemoveFromSuperview(); 

     webView.Dispose();