2012-08-05 27 views
10

Sto cercando di risolvere un sacco di perdite che il mio UIWebView sta causando e non è in grado di trovare la loro origine né una soluzione alternativa. Quello che faccio è di ottenere alcuni contenuti dal web attraverso una richiesta di rete, poi assemblare il mio HTML e caricarlo al volo:Perdite di memoria con UIWebView e Javascript

NSString* body = <some HTML>; 
NSString* html = [NSString stringWithFormat:kHTMLTemplate, [self scripts], [self styles], body]; 
[_webView loadHTMLString:html 
       baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]]; 

Ogni volta che c'è nuovi contenuti disponibili, eseguo loadHTMLString di nuovo per aggiornare la visualizzazione Web . Riuso la stessa vista web, stesso controller, stesso tutto.

Instruments mostra un modello molto strana in cui tutti gli oggetti fuoriusciti sono generali blocchi di varie dimensioni e nessuno di loro ha tutte le informazioni ad esso collegato: nessuna libreria responsabile, nessuna cornice responsabile, ecc Ogni volta che viene eseguita loadHTMLString , vengono aggiunte nuove perdite.

Sembra che ci siano diversi thread in S.O. circa UIWebView perdite di memoria. Ho provato tutti i suggerimenti che ho trovato (ad esempio, impostando lo NSURLCache su zero o resettandolo, ho provato a rilasciare l'UIWebView esistente e ne alloco uno nuovo ogni volta che ho nuovi dati, ecc.) Ma nulla ha aiutato.

Le mie indagini finora portano a un risultato chiaro: sembra che le perdite siano presenti solo se l'HTML che carico nella vista contiene alcuni Javascript. Se si nota la stringa html sopra, è composta da diversi componenti; uno è [self scripts] che è una funzione che restituisce semplicemente:

return @"<script type='text/javascript' src='jquery-1.4.4.min.js'></script>" 
     "<script type='text/javascript' src='jmy.js'></script>"; 

Se rimuovo questo, perdite ci sono. Ma le perdite appaiono non appena aggiungo un tag <script> al mio HTML. Hanno anche visualizzati se ho semplicemente includere il file jquery (o qualsiasi altro file js, come a questo):

return @"<script type='text/javascript' src='jquery-1.4.4.min.js'></script>"; 

Quindi, la domanda: qualcuno ha un'idea su ciò che sta succedendo qui? Includere chiaramente un file Javascript nel mio codice HTML sta rendendo la memoria perdite UIWebView.

Il fatto che le perdite appaiono sia quando ho riutilizzare lo stesso UIWebView oggetto o quando un'istanza di un nuovo ogni volta che ho contenuto, mi porta a pensare che ci deve essere qualcosa nel modo in cui i file javascript sono gestite da loadHTMLString che conduce alle perdite.

Qualcuno sa come potrebbe essere risolto?

enter image description here

+0

Questo potrebbe essere un bug in UIWebView. http://blog.techno-barje.fr/post/2010/10/04/UIWebView-secrets-part1-memory-leaks-on-xmlhttprequest/ –

+0

@ H2CO3: grazie, ho anche provato che ... nessun miglioramento. .. – sergio

+0

pensa che siamo salvati da iOS 8. Leggi questa risposta su WKWebView http://stackoverflow.com/questions/16514230/massive-memory-leak-in-ios-uiwebview –

risposta

11

ho finalmente trovato qualche indizio su ciò che sta accadendo e, soprattutto, una soluzione che vorrei condividere.

Posso confermare che la semplice inclusione di alcuni file javascript causava una perdita di memoria durante il ricaricamento della visualizzazione Web. Ho anche provato a creare un file con il contenuto HTML, quindi a caricarlo nello UIWebView tramite loadRequest e ricaricarlo tramite reload; le perdite erano sempre lì. Pubblicherò un radar per questo.

Ciò che mi ha salvato era usare innerHTML per aggiornare il contenuto della visualizzazione Web.Invece di basarsi su reload o loadHTMLString, ho inizializzato mio punto di vista web con un corpo vuoto (voglio dire, la sezione head era lì, compresi tutti i file JS necessari/CSS) e poi aggiornato è l'impostazione document.body.innerHTML:

body = [body stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setBody(\"%@\");", body]]; 

con setBody definito così:

var setBody = function(body) { 
    document.body.innerHTML = body; 
} 

ho ottenuto due vantaggi: l'aggiornamento visualizzazione web è diventato molto veloce (questo è un effetto di non aggiornare il DOM, che d'altra parte non è del tutto desiderabile nel complesso), e ci non c'erano perdite di memoria stavano eseguendo l'app sotto Strumenti. Lo svantaggio era che dovevo mettere a punto un paio di condizioni in cui l'app funzionava correttamente; in particolare:

  1. caricamento della visualizzazione Web (anche con una pagina corpo vuoto) prendere molto, quindi è necessario sincronizzare il primo aggiornamento del suo contenuto a quando il DOM è pronto;

  2. webViewDidFinishLoading sembra non affidabile: viene eseguito prima dello document.readyState diventa complete;

  3. document.documentElement.height, il mezzo ufficiale di recuperare l'altezza della pagina sembra non affidabile, troppo: soluzione sta ottenendo lo "stile calcolata" della parte body e leggere il suo valore height.

Spero che questo aiuti qualcun altro a scoprire che le sue visualizzazioni web stanno perdendo memoria.

Problemi correlati