2009-03-14 6 views
16

Ich baue eine Tabelle mit etwas Text, der HTML ist, also verwende ich ein UIWebView als Unteransicht meiner benutzerdefinierten Tabellenzellen. Ich war schon auf ein Problem gestoßen - als ich in der Tabelle nach unten scrollte, würde es die UIWebViews eine Sekunde dauern, um zu aktualisieren. Ich würde z. B. Zellen in den Zeilen 1, 2 und 3 anzeigen. Ich würde nach unten blättern, um 8, 9 und 10 zu sagen. Für einen Moment war der Inhalt von UIWebView, der in Zelle 8 sichtbar war der Inhalt von Zelle # 1, der Inhalt in Zelle # 9 war der von Zelle # 2 und so weiter.Wie verwende ich ein UIWebView in einer Tabellenzelle?

Ich habe gelernt, dass das Problem war, dass UIWebViews einfach ihren Text langsam rendern. Es wurde vorgeschlagen, den Inhalt stattdessen so schnell wie möglich in den UIWebView zu laden, anstatt zu warten, bis die Tabelle den cellForRowAtIndexPath empfängt. So, jetzt habe ich ein Domain-Objekt, das vorher nur den Textinhalt des WebView hatte - aber jetzt hat es tatsächlich einen Verweis auf das UIWebView selbst.

Aber jetzt einige der Inhalte in der UIWebView rendert, und wenn ich durch die Tabelle blättern die UIWebView zeigt nur als graue Box. Wenn ich die graue Box berühre, erhält sie tatsächlich die Berührung und aktualisiert das WebView - zum Beispiel, wenn ich einen Link berühre (was ich tun oder nicht tun kann, da die Box grau ist und es mit einem Glücksfall wäre), Die Seite, mit der verlinkt wurde, wird angefordert und korrekt angezeigt.

- (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]; 
} 

Antwort

9

Eine Möglichkeit, dies zu umgehen, wäre die Verwendung mehrerer UILabels mit jeweils unterschiedlichen Schriftarten. Platziere sie dann strategisch in der Zelle, damit sie wie zusammenhängender Text erscheinen. Ich habe das in einem UITableView mit sehr guten Ergebnissen gesehen.

Ein weiteres Leistungsproblem könnte sein, dass Sie UItableViewCell und seine Init-Methode übersteuern. Dies führt fast immer zu einer schlechten Performance in einem UITableView. Verwenden Sie stattdessen nur die regulären UITableViewCell-Instanzen und fügen Sie subviews zur contentView hinzu.

Dies wurde umfangreich von Matt Gallagher Easy Custom UITableView Drawing abgedeckt.

Eine andere beschriebene Methode war die Verwendung von Three20, die Ihnen auch formatierten Text geben kann.

Was Sie gerade versuchen, ist mit UIWebview nicht möglich.

Das Vorladen hilft nicht: das würde die Benutzeroberfläche verlangsamen, wenn UIWebViews offline gerendert werden; Sie sollten immer faulen Laden auf dem iPhone üben.

Das Einfügen von UIWebviews in eine UITableView wird mit einem möglicherweise inakzeptablen Leistungseinbruch verbunden sein. Sie müssen andere Mittel verwenden, um Ihr Ziel zu erreichen.

Leider ist NSAttributedString in UIKit nicht verfügbar, was Ihr Problem leicht lösen könnte.

+0

Ich akzeptierte diese eine b/c der Realität, dass dies nicht etwas ist, das mit einem UIWebView getan werden kann. Persönlich habe ich aufgehört, das Feature zu verlassen, aber ich werde bald wiederkommen - und was ich tun werde, anstatt ein TableView zu verwenden, simuliere es einfach mit HTML und CSS und setze es in ein einziges WebView. Dann verwende ich ein WebViewDelegate, um Klicks auf Links zu "abfangen" und zu bestimmen, ob andere Webinhalte angezeigt werden sollen oder ob andere Aktionen in meiner Anwendung ausgeführt werden sollen. – bpapa

0

Haben Sie untersucht, ob die Methode -prepareForReuse für die Unterklasse Ihrer Tabellenzelle überschrieben wird? Wenn die Zellen beim Scrollen nicht aktualisiert werden, ist es möglich, dass der Inhalt der wiederverwendbaren Zellen nicht gelöscht und zurückgesetzt wird.

1

Sie sagten 'calleForRowAtIndexPath', was bedeutet, dass 'cellForRowAtIndexPath' eine UITableView-Methode ist, die aufgerufen wird, wenn eine Zeile sichtbar wird und eine Zelle erstellt werden muss. Stellen Sie sicher, dass Sie bei dieser Methode den Zelleninhalt ordnungsgemäß initialisieren und aktualisieren.

+0

Ja, ich tat dies aus dem Speicher, die nicht der beste Weg ist, um Fragen zu schreiben. – bpapa

+0

Kannst du klarstellen, "wenn ich mit dem Scrollen beginne, werden die Web-Ansichten nicht aktualisiert". Scrollen Sie innerhalb der Webansicht oder scrollen Sie in der Tabellenansicht nach unten? Welcher Inhalt ist in der Webansicht und was sollte er ändern? – Akusete

+0

Aktualisiert dritten Absatz der Frage besser beschreiben, was ich sehe. – bpapa

2

Dies ist nicht die ursprüngliche Frage beantwortet, aber einen Schritt zurück und Blick auf das größere Bild, wenn Sie versuchen, einen Hyperlink in einer Tabellenzelle anzuzeigen, bedeutet das, wenn Sie darauf klicken, öffnet es ein Webbrowser? Wäre es genauso, wenn Sie formatierten Text in der Tabellenzelle anzeigen würden, der aussieht oder auf einen Link verweist, aber einen separaten Bildschirm mit einer Vollbild-Webansicht öffnet, mit der Sie auf den Link tippen können?

4

Wenn der Inhalt in der Web-Ansicht zu formatierten Text oder Hyperlinks beschränkt Sie einen Blick auf die Three20 Projekt teilnehmen möchten: http://github.com/joehewitt/three20/tree/master

Seine TTStyledText Klasse hat die Unterstützung für <b>, <i>, <img>, and <a> Tags im Inhalt. Wahrscheinlich leichter als Webansichten.

0

Mein Verständnis ist, dass ein WebView wird nicht gerendert, es sei denn Sie initiieren das Laden von es nach viewDidLoad() passiert.

+1

UIWebView scheint sein Rendering zu machen, nachdem die Steuerung zum RunLoop zurückkehrt. Wenn Sie also versuchen, JavaScript auszuführen, können Sie dies nicht in - [viewDidLoad] oder - [viewWillAppear] tun. Sie können dies möglicherweise in der Methode des Web-View-Delegaten tun, wenn die Web-Ansicht fertig geladen ist. – lucius

6

Hier ist meine aktualisierte Antwort: Ich habe eine Tabelle mit einem großen UIWebView implementiert, um formatierten Text in Tabellenzellen in meiner eigenen Twitter-Client-App, HelTweetica (mit Quelle verfügbar) zu setzen. Es funktioniert ziemlich gut, solange Sie das Layout in HTML und CSS verstehen.

Sie erstellen einfach eine NSMutableString und fügen Sie die HTML-Zeilen, die Ihr Dokument bilden. Sie können auf externe Dateien wie CSS-Dateien verweisen, die sich in der Sandbox Ihrer App befinden. „: //file.txt youraction“, die Ihre Web-Ansicht delegieren abfangen und verarbeiten kann als Ersatz IBAction s: Sie können benutzerdefinierte URL-Aktionen wie Set

- (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]; 
} 

Und Sie können mit Javascript, Teile der Seite neu zu laden :

Verwandte Themen