2011-01-11 11 views
9

Qualcuno conosce un modo o ha un'idea creativa su come ottenere una UIImage che viene renderizzata da UIWebView? Il problema è che deve essere su un thread in background.Creare un UIImage rendendo UIWebView su un thread in background - iPhone

Elaborerò: Sto cercando di ottenere l'immagine da più UIWebViews ogni secondo + -, e visualizzarla sullo schermo (ovviamente iPhone). Poiché il rendering di un livello in un CGContext è un lavoro che consuma CPU, non vorrei utilizzare il thread principale, quindi non appendere l'interfaccia utente.

I miei tentativi finora sono state:

  • Ho cercato di usare renderInContext sul livello del WebView al UIGraphicalContext, ma l'errore _WebTryThreadLock caduto le visualizzazioni.

  • Ho provato a creare uno CGBitmapContext ea renderlo il livello della vista web, ma ho ottenuto lo stesso risultato.

  • Ho provato ad implementare un metodo copy (aggiungendo una categoria) a CALayer, che ha copiato in profondità tutte le proprietà pubbliche e i sottolivelli. Successivamente, ho provato a eseguire lo renderInContext livello che ho copiato. Ho ottenuto un UIImage che era parzialmente "corretto" - ovvero non tutti i livelli sono stati renderizzati, quindi ad esempio, otterrei solo l'intestazione del sito Web (o il piè di pagina, o corpo o barra di ricerca, o solo alcuni di le cornici). Il livello di UIWebview consiste di tutti i tipi di CALayer sottoclassi, quindi questo è probabilmente il motivo per cui questo approccio non ha funzionato.

  • Ho provato a impostare kCATransactionDisableActions in un CATransaction, ma non sembra modificare questo comportamento (nessuno di loro).

Sono abbastanza vicino a rinunciare.

C'è un salvatore tra voi?

+0

+1 domanda difficile –

risposta

4

UIWebView odia, e voglio dire odia davvero, avendo fatto qualcosa su di esso in un thread in background. UIKit non è completamente thread-safe. Il disegno su un contesto grafico è (è stato aggiunto in iOS 4), ma non crea UIViews su un thread secondario.

Stai creando UIWebViews dal thread principale? Hai forse un codice da condividere? Sospetto che i tuoi problemi siano causati dal fatto che stai cercando di eseguire operazioni su UIWebView su un thread secondario. L'operazione di disegno per il rendering dei contenuti della vista come immagine può essere eseguita dal thread principale, ma non è possibile creare la vista stessa.

+3

Sto creando UIWebViews sul thread principale. Non potrei essere più d'accordo sulla parte "odia";), e sono anche d'accordo che è possibile disegnare in un contesto grafico, ma sfortunatamente sembra che il layout di UIWebView sembra bloccare, in certe condizioni, il thread associato a lo stesso UIWebView (non il thread principale, ma quello creato da iOS per gestirlo), che lo fa sconcertare quando il blocco viene eseguito da un thread secondario. Il layout di UIWebView è costruito con poche sottoclassi API private di CALayer (WebLayer ecc.). – Gilbert

+0

Ho visto problemi simili prima con le visualizzazioni web, anche se sono stati limitati al simulatore - hai ragione, probabilmente ha a che fare con una delle sottoclassi private. Scusa, non posso essere più d'aiuto. – lxt

0

Ho lavorato anche a questo.

In una discussione creo una gerarchia di viste, loop finché la visualizzazione Web non ha completato il caricamento del contenuto.

WebView creo è dentro di viewdidload-- di un UIViewController che ho provato a fare

if ([NSThread isMainThread] == NO) {[self performselectorOnMainThread: @selector(viewDidLoad)return;)} 

E io ho fatto lo stesso per il dealloc'ing WebView.

Ma questo non ha funzionato ..Ho appena scoperto che evitiamo le eccezioni di UIWebView finché non raggiungiamo il pool di autorelease ...

Sto utilizzando gli strumenti per capire perché.

Ecco la mia strategia di attacco ... Ho intenzione di eseguire l'operazione di rendering sul thread principale con una visualizzazione fuori schermo, con un thread separato che esegue una sorta di coda per gestirli. Sono preoccupato per il ritardo dell'interfaccia utente, quindi dovrà essere abbastanza efficiente.

+0

Sì, questo è il trucco ... Esegui i selettori per creare il rendering su un thread separato, interrogare lo stato del caricamento su un thread sussidiario, quindi eseguire il rendering sul thread principale quando è pronto. – user438350

+2

Questa è fondamentalmente la mia soluzione attuale. Ma non è una buona cosa, perché ho troppa interfaccia utente a causa di esso (e l'unica cosa che faccio sul thread principale è l'effettivo processo di rendering di base). – Gilbert

Problemi correlati