如何在表格单元格中使用UIWebView?

bpa*_*apa 16 iphone cocoa-touch uiwebview uitableview

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

我了解到问题是UIWebViews只是缓慢地渲染文本.有人建议我尽快将内容预先加载到UIWebView中,而不是等到表收到cellForRowAtIndexPath.所以现在,我有一个Domain Object,它之前只有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];
}
Run Code Online (Sandbox Code Playgroud)

Cor*_*oyd 9

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

另一个性能问题可能是你覆盖了UItableViewCell和它的init方法.这几乎总是导致UITableView中的性能不佳.而只是使用常规的UITableViewCell实例并将子视图添加到它的contentView.

Matt Gallagher的Easy Custom UITableView Drawing广泛涵盖了这一点.

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

您目前正在尝试使用UIWebview无法完成的操作.

预加载无济于事:当UIWebviews在屏幕外呈现时,这会降低UI的速度; 你应该总是在iPhone上练习延迟加载.

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

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


luc*_*ius 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];
}
Run Code Online (Sandbox Code Playgroud)

你可以使用javascript重新加载部分页面:

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