【问题标题】:How do I use a UIWebView in a Table Cell?如何在表格单元格中使用 UIWebView?
【发布时间】:2009-03-14 21:54:08
【问题描述】:

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

我了解到问题在于 UIWebView 只是缓慢地呈现它们的文本。建议尽快将内容预加载到 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];
}

【问题讨论】:

    标签: iphone cocoa-touch uitableview uiwebview


    【解决方案1】:

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

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

    这已被 Matt Gallagher 的Easy Custom UITableView Drawing 广泛报道。

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

    您目前正在尝试的操作无法通过 UIWebview 完成。

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

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

    很遗憾,NSAttributedString 在 UIKit 中不可用,这可以轻松解决您的问题。

    【讨论】:

    • 我最终接受了这一事实,即这不是 UIWebView 可以完成的。就我个人而言,我最终放弃了这个功能,但我很快就会重新审视——我要做的不是使用 TableView,而是使用 HTML 和 CSS 模拟它,并将其放入单个 WebView 中。然后,我将使用 WebViewDelegate 对链接的“拦截”点击进行排序,并确定是否在我的应用程序中显示其他 Web 内容或执行其他操作。
    【解决方案2】:

    所以这是我更新的答案:我已经使用一个大的 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];
    }
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

          • 是的,我是凭记忆这样做的,这不是写问题的最佳方式。
          • 你能澄清一下“当我开始滚动网页视图时不会更新”。您是在 webview 中滚动还是向下滚动 table view? webview 中有什么内容,应该改成什么内容?
          • 更新了问题的第三段,更好地描述了我所看到的。
          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

            我的理解是 WebView 不会呈现,除非您在 viewDidLoad() 发生之后启动它的加载。

            【讨论】:

            • UIWebView 似乎在控制返回到主 RunLoop 后进行渲染,因此如果您尝试执行 JavaScript,则无法在 -[viewDidLoad] 或 -[viewWillAppear] 中执行此操作。当 Web 视图完成加载时,您可能可以在 Web 视图委托的方法中执行此操作。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-11-20
            • 1970-01-01
            • 2012-07-12
            • 2019-04-28
            • 1970-01-01
            • 2015-12-31
            • 2016-11-05
            相关资源
            最近更新 更多