16

我正在构建一个带有一些 HTML 文本的表格,因此我使用 UIWebView 作为我的自定义表格单元格的子视图。我已经遇到了一个问题——当我在表格中向下滚动时,UIWebViews 需要一秒钟才能更新。例如,我将查看编号为 1、2 和 3 的行的单元格。我会向下滚动到 8、9 和 10。有一会儿,在单元格 #8 中可见的 UIWebView 的内容是单元格#1 中的内容,单元格#9 中的内容是单元格#2 中的内容,依此类推。

我了解到问题在于 UIWebViews 只是缓慢地渲染它们的文本。建议尽快将内容预加载到 UIWebView 中,而不是等到表接收到 cellForRowAtIndexPath。所以现在,我有一个域对象,它之前只有 WebView 的文本内容 - 但现在它实际上有对 UIWebView 本身的引用。

但是现在 UIWebView 中的一些内容呈现,当我滚动表格时 UIWebView 仅显示为灰色框。如果我触摸灰色框,它实际上会接收触摸并更新 WebView - 例如,如果我触摸一个链接(我可能会或可能不会这样做,因为该框是灰色的,而且很幸运),链接到的页面将被请求并正确显示。

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

7 回答 7

9

解决这个问题的一种方法是使用多个 UILabel,每个 UILabel 都有不同的字体。然后策略性地将它们放置在单元格中,使它们看起来像连续的文本。我已经在 UITableView 中看到了这一点,效果非常好。

另一个性能问题可能是您正在覆盖 UItableViewCell 和它的 init 方法。这几乎总是会导致 UITableView 的性能不佳。相反,只需使用常规 UITableViewCell 实例并将子视图添加到它的 contentView。

这已被 Matt Gallagher 的Easy Custom UITableView Drawing广泛涵盖。

描述的另一种方法是使用 Three20,它也可以为您提供样式文本。

您当前尝试的操作无法使用 UIWebview 完成。

预加载无济于事:当 UIWebview 在屏幕外渲染时,这会减慢 UI;你应该经常在 iPhone 上练习延迟加载。

将 UIWebviews 放入 UITableView 会带来潜在的不可接受的性能影响。您将需要使用其他方式来实现您的目标。

不幸的是,NSAttributedString 在 UIKit 中不可用,它可以轻松解决您的问题。

于 2009-05-30T05:59:28.203 回答
6

所以这是我更新的答案:我已经使用一个大的 UIWebView 实现了一个表格,将样式化文本放在我自己的 Twitter 客户端应用程序HelTweetica的表格单元格中(有可用的源代码)。只要您了解如何在 HTML 和 CSS 中进行布局,它就可以很好地工作。

您只需创建一个NSMutableString并添加构成文档的 HTML 行。您可以引用应用程序沙箱中的外部文件,例如 CSS 文件。您可以设置自定义 URL 操作,例如“youraction://file.txt”,您的 Web 视图代理可以拦截和处理这些操作作为替换IBActions:

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

您可以使用 javascript 重新加载页面的某些部分:

- (void) refreshTabArea {
    NSString *html = [self stringByEscapingQuotes: [self tabAreaHTML]];
    NSString *js = [NSString stringWithFormat: @"document.getElementById(\"tab_area\").innerHTML = \"%@\";", html];
    [self.webView stringByEvaluatingJavaScriptFromString:js];
}
于 2010-04-28T19:27:28.607 回答
4

如果 Web 视图中的内容仅限于样式文本或超链接,您可能需要查看 Three20 项目:http: //github.com/joehewitt/three20/tree/master

它的TTStyledText类支持<b>, <i>, <img>, and <a>内容中的标签。可能比 webviews 更轻量级。

于 2009-05-27T19:03:40.807 回答
2

这不是回答最初提出的问题,而是退后一步,看看更大的图景,如果您尝试在表格单元格中显示超链接,这是否意味着当您单击它时会打开 Web 浏览器?如果您在表格单元格中显示样式文本,看起来像或提示链接,但打开一个带有全屏 Web 视图的单独屏幕,让您点击链接,会不会一样?

于 2009-03-20T21:38:10.700 回答
1

您说“由 setRowAtIndexPath 调用”,您可能是指“cellForRowAtIndexPath”,它是当行变得可见并需要创建单元格时调用的 UITableView 方法。确保在此方法中正确初始化和更新单元格内容。

于 2009-03-16T04:43:21.420 回答
0

您是否考虑过在表格单元子类上覆盖 -prepareForReuse 方法?如果滚动时单元格似乎没有更新,则可能是可重用单元格的内容没有被清除和重置。

于 2009-03-14T23:24:47.123 回答
0

我的理解是,除非您在 viewDidLoad() 发生后开始加载它,否则 WebView 不会呈现。

于 2010-04-27T19:04:54.193 回答