ios - NSAttributedString 中的 HTML 呈现速度非常慢

标签 ios swift uitableview grand-central-dispatch nsattributedstring

我的 UITableView 带有动态调整大小的单元格,以 HTML 格式显示评论列表,我遇到了 NSAttributedString 呈现 HTML 内容非常慢的问题!

这是分析器的快照。

enter image description here

我尝试将 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()
      })
   })

看起来如下 enter image description here

请指教如何加速渲染和修复单元格布局。

谢谢!

更新:

解决了单元格委托(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 之前:

Before

紧接着:

enter image description here

所以您可以想象,有时启动这一切需要将近一秒钟的时间。 后续调用要快得多。我的解决方法是在 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/

相关文章:

objective-c - iOS 搜索中 NSMutableArray 结果的更好方法

ios - subview 中的 UIButton 调用父 View 中的方法

swift - 如何使用 swift 4 在 ios firebase 中存储用户数据

ios - 如何设置每次重复不同内容的每日通知?

swift - 当我想通过 tableViewController 中的 indexPath 访问行时出错

iphone - Plist 到 UITableView

android - 在 React Native 中保存时旋转图像的问题

ios - NSPredicate 并忽略指定格式的字符串 Objective c

ios - Swift 自定义 UIAlertView

ios - 所有数据都显示在一行中