我的 UITableView 带有动态调整大小的单元格,以 HTML 格式显示评论列表,我遇到了 NSAttributedString 呈现 HTML 内容非常慢的问题!
这是分析器的快照。
我尝试将 NSAttributedString 初始化放在单独的线程中,但仍然很慢,用户在渲染 HTML 时看到空单元格,最后当它完成渲染时单元格布局不正确。
dispatch_async(GlobalQueue, {
let html = NSAttributedString(
data: self.comment.htmlBody.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: false)!,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil,
error: nil)
dispatch_async(MainQueue, {
self.commentLabel.attributedText = html
self.commentLabel.font = UIFont(name: "HelveticaNeue-Light", size: 14.0)!
if let writer = self.comment.author {
self.authorLabel.text = writer.name
}
self.layoutIfNeeded()
})
})
请指教如何加速渲染和修复单元格布局。
谢谢!
更新:
解决了单元格委托(delegate)和标志,指示属性字符串已初始化。也许会帮助某人:
// TicketCell
private var isContentInitialized = false
private var commentAttributedString:NSAttributedString?
var delegate: TicketCommentCellDelegate?
var indexPath: NSIndexPath!
var comment: TicketComment! {
willSet {
if newValue != self.comment {
self.isContentInitialized = false
}
}
didSet{
self.configure()
}
}
...
private func configure() {
if isContentInitialized {
// here might be activity indicator stop
...
if let writer = self.comment.author {
self.authorLabel.text = writer.name
}
}
else {
// here might be activity indicator start
dispatch_async(GlobalQueue, {
self.commentAttributedString = NSAttributedString(
data: self.comment.htmlBody.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: false)!,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil,
error: nil)
self.isContentInitialized = true
// here might be spinner stop
dispatch_async(MainQueue, {
self.delegate?.ticketCommentCellDidRenderCommentHTML(self)
})
})
}
}
...
protocol TicketCommentCellDelegate {
func ticketCommentCellDidRenderCommentHTML(cell: TicketCommentCell)
}
// TableViewDataSource
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(kTicketCommentCellIdentifier, forIndexPath: indexPath) as! TicketCommentCell
cell.indexPath = indexPath
cell.delegate = self
cell.comment = self.rows[indexPath.section][indexPath.row]
return cell
}
// MARK: - TicketCommentCellDelegate
func ticketCommentCellDidRenderCommentHTML(cell: TicketCommentCell) {
self.tableView.reloadRowsAtIndexPaths([cell.indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = self.commentCell
cell.comment = self.rows[indexPath.section][indexPath.row]
cell.setNeedsDisplay()
cell.setNeedsLayout()
let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
return height
}
最佳答案
关于将 HTML 解析为字符串的缓慢问题:第一次创建 HTML 的属性字符串时,iOS 会创建解析字符串所需的各种额外线程,其中包括 JavascriptCore 引擎。
在从 HTML 解析第一个 NSAttributedString 之前:
紧接着:
所以您可以想象,有时启动这一切需要将近一秒钟的时间。
后续调用要快得多。我的解决方法是在 Appdelegate 的 application:didFinishingLaunchingWithOptions:
函数中解析 HTML,以便在需要时我在内存中拥有所有必要的框架(Objective-C):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSMutableAttributedString *attrStringFromHtml = [[NSMutableAttributedString alloc]
initWithData: [@"<span>html enabled</span>" dataUsingEncoding:NSUnicodeStringEncoding
allowLossyConversion:NO]
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
documentAttributes:nil error:nil];
NSLog(@"%@",[attrStringFromHtml string]);
return YES;
}
另见 this answer .
关于ios - NSAttributedString 中的 HTML 呈现速度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31852655/