我有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()
})
})
请建议如何加快渲染速度并修复单元格布局。
谢谢!
更新:
使用单元格委托和标志解决,表明属性字符串已初始化。也许会帮助别人:
// 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
}
答案 0 :(得分:12)
将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。