2009-03-14 5 views
16

Sto costruendo una tabella con del testo che è HTML, quindi sto usando una UIWebView come sottoview delle mie celle di tabella personalizzate. Ho già avuto un problema: mentre scendevo nel tavolo, l'UIWebViews avrebbe richiesto un secondo per l'aggiornamento. Ad esempio, visualizzerei Celle alle righe numerate 1, 2 e 3. Scorrerei verso il basso per dire 8, 9 e 10. Per un momento, il contenuto di UIWebView che era visibile nella cella n. 8 era il contenuto della cella n. 1, il contenuto nella cella n. 9 era quello dalla cella n. 2 e così via.Come utilizzare un UIWebView in una cella di tabella?

Ho appreso che il problema era che UIWebViews semplicemente rendeva il testo lentamente. È stato suggerito invece di precaricare il contenuto in UIWebView non appena possibile invece di aspettare finché la tabella non riceva cellForRowAtIndexPath. Quindi, ora ho un oggetto dominio che prima aveva solo il contenuto testuale di WebView - ma ora ha effettivamente un riferimento a UIWebView stesso.

Ma ora alcuni dei contenuti nel rendering UIWebView e quando si scorre la tabella UIWebView mostra solo una casella grigia. Se tocco la casella grigia, riceverà effettivamente il tocco e aggiornerò la visualizzazione Web, ad esempio se toccherò un collegamento (cosa che potrei o non potrei fare, poiché la casella è grigia e sarebbe un colpo di fortuna), la pagina a cui è stato collegato sarà richiesta e visualizzata correttamente.

- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier { 
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) { 
      // I suppose this isn't necessary since I am just getting it from the 
      // Domain Object anyway 
    content = [[UIWebView alloc] initWithFrame:CGRectZero]; 
    content.backgroundColor = [UIColor blackColor]; 
    [self addSubview:content]; 
    [content release]; 
} 
return self; 
} 

// called by cellForRowAtIndexPath 
- (void)setMyDomainObject:(MyDomainObject*)anObject { 
UIWebView *contentWebView = anObject.contentWebView; 
int contentIndex = [self.subviews indexOfObject:content]; 
[self insertSubview:contentWebView atIndex:contentIndex]; 
} 

risposta

9

Un modo per risolvere questo problema è utilizzare diversi UILabels, ciascuno con caratteri diversi. Quindi posizionali strategicamente all'interno della cella in modo da farli apparire come un testo contiguo. Ho visto questo fatto in un UITableView con ottimi risultati.

Un altro problema di prestazioni potrebbe essere l'overflow di UItableViewCell e il suo metodo init. Questo porta quasi sempre a prestazioni scadenti in un UITableView. Invece, basta usare le normali istanze di UITableViewCell e aggiungere subviews a contentView.

Questo è stato ampiamente trattato da Matt Gallagher Easy Custom UITableView Drawing.

Un altro metodo descritto era l'uso di Three20, che può darti anche un testo in stile.

Attualmente non è possibile eseguire ciò che si sta tentando con UIWebview.

Il preloading non è d'aiuto: questo rallenterebbe l'interfaccia utente quando UIWebviews viene reso fuori schermo; devi sempre esercitarti con il caricamento lento su iPhone.

Mettere UIWebviews in un UITableView arriverà con un colpo di performance potenzialmente inaccettabile. Avrai bisogno di usare altri mezzi per raggiungere il tuo obiettivo.

Sfortunatamente, NSAttributedString non è disponibile in UIKit, che potrebbe facilmente risolvere il problema.

+0

Ho finito per accettare questo b/c della realtà che questo non era qualcosa che può essere fatto con un UIWebView. Personalmente ho finito per abbandonare la funzione, ma la rivedrò presto - e quello che farò invece di usare un TableView è semplicemente simularlo usando HTML e CSS, e metterlo in una singola WebView. Quindi userò un WebViewDelegate per ordinare i clic "intercettati" sui collegamenti e determinare se mostrare altro contenuto Web o fare qualche altra azione nella mia applicazione. – bpapa

0

Hai guardato in override del metodo -prepareForReuse sul tuo sottoclasse cella di una tabella? Se le celle non sembrano aggiornarsi quando si scorre, è possibile che il contenuto delle celle riutilizzabili non venga cancellato e resettato.

1

Hai detto "chiamato da setRowAtIndexPath", potresti voler dire "cellForRowAtIndexPath" che è un metodo UITableView chiamato quando una riga diventa visibile e deve creare una cella. Assicurarsi che in questo metodo si inizializzi e si aggiorni correttamente il contenuto della cella.

+0

sì, stavo facendo questo dalla memoria che non è il modo migliore per scrivere domande. – bpapa

+0

Puoi chiarire "quando inizio a scorrere le viste web non aggiornare". Stai scorrendo all'interno della visualizzazione Web o scorrendo verso il basso la vista tabella? Quale contenuto è presente nella visualizzazione Web e a cosa deve essere modificato? – Akusete

+0

Il terzo paragrafo della domanda aggiornato descrive meglio quello che sto vedendo. – bpapa

2

Questo non sta rispondendo alla domanda originale, ma facendo un passo indietro e guardando l'immagine più grande, se si sta tentando di visualizzare un collegamento ipertestuale in una cella di tabella, significa che quando si fa clic su di esso si apre un browser web? Sarebbe lo stesso se mostrassi un testo stilizzato nella cella della tabella che assomiglia o suggerisca un link, ma apri una schermata separata con una visualizzazione web a schermo intero che ti permetta di toccare il link?

4

Se il contenuto nella vista web è limitato a testo o collegamenti ipertestuali si potrebbe desiderare di dare un'occhiata al progetto Three20 stile: http://github.com/joehewitt/three20/tree/master

La sua classe TTStyledText ha il supporto per i tag <b>, <i>, <img>, and <a> nel contenuto. Probabilmente più leggero delle visioni web.

0

La mia comprensione è che una WebView non verrà visualizzata a meno che non si avvii il caricamento di esso DOPO viewDidLoad() si verifica.

+1

UIWebView sembra eseguire il rendering dopo che il controllo ritorna al RunLoop principale, quindi se si tenta di eseguire JavaScript, non è possibile farlo in - [viewDidLoad] o - [viewWillAppear]. Potresti essere in grado di farlo nel web view del metodo delegato per quando la visualizzazione web ha terminato il caricamento. – lucius

6

Quindi ecco la mia risposta aggiornata: ho implementato una tabella utilizzando un UIWebView grande per inserire testo stilizzato all'interno di celle di tabella nella mia app client Twitter, HelTweetica (con sorgente disponibile). Funziona molto bene finché capisci come fare il layout in HTML e CSS.

È sufficiente creare un NSMutableString e aggiungere le linee di codice HTML che costituiscono il documento. Puoi fare riferimento a file esterni come i file CSS presenti nella sandbox della tua app. È possibile impostare le azioni URL personalizzato come ad esempio "youraction: //file.txt" che la vista web delegato può intercettare e di processo in sostituzione IBAction s:

- (void) refreshWebView { 
    TwitterAccount *account = [twitter currentAccount]; 
    NSMutableString *html = [[NSMutableString alloc] init]; 
    // Open html and head tags 
    [html appendString:@"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"]; 
    [html appendString:@"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]; 
    [html appendString:@"<head>\n"]; 
    [html appendString:@"<meta name='viewport' content='width=device-width' />"]; 
    [html appendString:@"<link href='style-ipad.css' rel='styleSheet' type='text/css' />"]; 
    [html appendString:@"<script language='JavaScript' src='functions.js'></script>"]; 

    // Body 
    [html appendString:@"</head><body><div class='artboard'>"]; 

    // [...] 

    // Close artboard div, body. and html tags 
    [html appendString:@"</div></body></html>\n"]; 

    NSURL *baseURL = [NSURL fileURLWithPath: [[NSBundle mainBundle] bundlePath]]; 
    [self.webView loadHTMLString:html baseURL:baseURL]; 
    [html release]; 
} 

E è possibile ricaricare le parti della pagina utilizzando javascript :

- (void) refreshTabArea { 
    NSString *html = [self stringByEscapingQuotes: [self tabAreaHTML]]; 
    NSString *js = [NSString stringWithFormat: @"document.getElementById(\"tab_area\").innerHTML = \"%@\";", html]; 
    [self.webView stringByEvaluatingJavaScriptFromString:js]; 
}