2009-06-01 5 views
8

Ho un'applicazione che utilizza UIWebViews in diversi controller di vista. Lo UIWebViews viene utilizzato per il rendering di html generato localmente, non è richiesto un accesso lento alla rete.Rimandare viewWillAppear fino a webViewDidFinishLoad

Per risparmiare memoria, li carico solo su richiesta, come richiesto dal callback del viewcontroller viewWillAppear. (E scaricare le istanze fuori schermo in risposta ai messaggi didReceiveMemoryWarning.)

Il problema è che l'utente può vedere il rendering del codice HTML, a volte accompagnato da bagliori di stile e altri artefatti spiacevoli assortiti. Preferirei molto che il rendering fosse fatto fuori dallo schermo e rivelasse la vista completamente renderizzata quando è pronta.

Sarebbe molto ordinato di essere in grado di restituire viewWillAppear fino a quando UIWebView non sarà completamente visualizzato. Ma come?

Dico allo UIWebView cosa inviare inviandolo un messaggio loadHTMLString:baseURL:. Questo è asincrono, e qualche volta (presto) più tardi il delegato della webview viene richiamato webViewDidFinishLoad.

Ho provato a eseguire un runloop all'interno di viewWillAppear, eseguendo il NSDefaultRunLoopMode o UITrackingRunLoopMode. Questo funziona nel simulatore (si lamenta con il registro

[CATransaction Sincronizza] chiamato all'interno della transazione

ma funziona), ma su un dispositivo che deadlock, con webViewDidFinishLoad mai essere chiamato.

(Inoltre, sembra che la proprietà di carico UIWebView non funziona. Almeno, dopo che io chiamo loadHTMLString:baseURL: e prima di ottenere la richiamata non è vero.)

+0

La proprietà "loading" funziona, ma il caricamento viene effettivamente attivato solo quando UIWebView è sullo schermo (se si traccia 'webViewDidStartLoad' e' webViewDidFinishLoad'). I suggerimenti tendono a dire "aggiungilo allo schermo con un'opacità di 0,01", ma questo non aiuta un controllore di vista che non è ancora sullo schermo .... –

risposta

3

Un sacco di soluzioni qui credo. Uno veloce è quello di caricare UIWebView con la sua proprietà nascosta impostata su SÌ. Quindi impostare il tuo UIViewController come delegato UIWebViews e implementare:

- (void)webViewDidFinishLoad:(UIWebView *)webView

in cui si imposta la proprietà torna a NO.

Una cosa da notare è che webViewDidFinishLoad verrà attivato più volte se si dispone di contenuto incorniciato/incorporato. Quindi devi tenere traccia di questo. Non dovrebbe essere un problema se si sta caricando il contenuto locale.

+0

Questa soluzione ha l'utente che guarda un display vuoto mentre la pagina è disegnato fuori dallo schermo. (Per la mia applicazione ho uno sfondo con cui renderizzare la pagina trasparente di fronte, quindi è qualcosa da guardare, ma ...) Sarebbe meglio modellare altre app che mostrano l'elemento di controllo (pulsante o voce di elenco) premuto mentre la pagina viene sottoposta a rendering e solo in seguito viene animata la vista completamente renderizzata. – cluesque

+0

Poi il target/selector del pulsante guida il rendering e fa avanzare la pagina quando finisce (webViewDidFinishLoad: come suggerisce il singlewerker) –

+0

webViewDidFinishLoad: non verrà chiamato fino a quando UIWebView non verrà spostato sullo schermo .... –

0

Mi piace di più la soluzione di monowerker, ma un'altra soluzione sarebbe quella di mantenere sempre la UIWebView già renderizzata (in qualche oggetto più permanente rispetto al controller di visualizzazione). Lo farei solo se l'aspetto della soluzione di monowerker è troppo dirompente.

+0

L'UIWebView consuma un sacco di memoria, ed è la prima cosa gettato in mare quando otteniamo un avviso di memoria insufficiente. anche uno dei miei casi d'uso è rendering dettaglio di un oggetto selezionato da una vista elenco (ad esempio, in Mail viene visualizzato un elenco di messaggi, tocca uno e leggere tutto) e quindi non può rendere fino a quando so che è oggetto essere visto – cluesque