UITableView滚动不平滑的原因是NSAttributedString。

3

我正在使用NSAttributedString将HTML字符串转换为attributedString。 我已经转换了它,但是由于单元格中的label,因此我在cellForRowAtIndex中编写了下面的代码,当我应用此代码时,表视图无法平稳滚动。 如果我用简单文本替换这个代码,它可以平稳滚动。

 cell.lblDescription.setHTMLFromString(htmlText: model.strItineraryDescription)

我已将 html字符串 转换为 属性字符串
extension UILabel {

    func setHTMLFromString(htmlText: String) {
        let modifiedFont = NSString(format:"<span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size: \(self.font!.pointSize)\">%@</span>" as NSString, htmlText) as String


        //process collection values
        let attrStr = try! NSAttributedString(
            data: modifiedFont.data(using: .unicode, allowLossyConversion: true)!,
            options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue],
            documentAttributes: nil)


        self.attributedText = attrStr
    }

}

我的 html 字符串 是:
<strong><u>Featured Program</u></strong></p>
\n<ol>
\n  <li>Arrival at Delhi airport. You will receive by our representative.</li>
\n  <li>Driving to Agra and exploring the city.</li>
\n  <li>Back to Hotel for Overnight stay.</li>
\n</ol>
\n<p><strong>City Features</strong></p>
\n<ol>
\n  <li><strong>Visit to Agra Fort \U2013 </strong>Former Name Badalgarh, Shah-Jahan spent his last eight years here. You can watch the mesmerizing view of Taj Mahal from this fort just like Shah Jahan.</li>
\n  <li><strong>Visit to Taj Mahal \U2013</strong> It took 21 years to build and stood in 1653. The palace is considered as the symbol of love. Shah Jahan built this wonder in the memory of his wife Mumtaj Mahal.</li>
\n</ol>
\n<p><strong>(Both Agra Fort and Taj Mahal are UNESCO Declared world heritage site)</strong>

NeverHopeless的回答是实现您需求的完美方式。@NeverHopeless 不错!!!+1 - Shardul
2个回答

3
这个 html2AttributedString 是做什么的?它是否在 cellForRowAtIndexPath 时将 HTML 转换为属性字符串?如果是,这就是实际花费时间的原因。我们可以在模型中缓存 HTML 的等效属性字符串,以便在重新加载时获取已准备好的属性字符串,从而以牺牲内存为代价加快速度。例如,伪代码如下:
class MyModel
{
    var myHTML: String = ""
    var myHTML2AttributedString: String = ""
}


class ModelMapping
{
  ...
  myModel.myHTML = responseFromJSON["htmlText"]
  myModel.myHTML2AttributedString = customFuncToConvertHTMLToAttributed(myModel.myHTML)
  ...
}

class ViewController
{
  ...
  cell.lblDescription.attributedText = myModel.myHTML2AttributedString // This one would be cached Attributed string equivalent of HTML string.
  ...
}

希望能对您有所帮助!
编辑:
class MyModel
{
    var myAttributedHTML: NSMutableAttributedString = ""
    var strItineraryDescription: String = ""

    func prepareHTMLFromString() {
        let modifiedFont = NSString(format:"<span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size: \(self.font!.pointSize)\">%@</span>" as NSString, self.strItineraryDescription) as String


        //process collection values
        let attrStr = try! NSAttributedString(
            data: modifiedFont.data(using: .unicode, allowLossyConversion: true)!,
            options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue],
            documentAttributes: nil)


        myAttributedHTML = attrStr.mutableCopy()
    }
}

class MyViewController
{
   ...
   cell.lblDescription.attributedText = myModel.myAttributedHTML
   ...
}

class ResponseHandler
{
   ...
   myModel.strItineraryDescription = responseFromServer["myHTML"]
   myModel.prepareHTMLFromString()
   ...
}

1
@VinodKumar,好的,我的意思是不要在单元格显示时准备你的属性字符串,而是在获取model.strItineraryDescription的值时同时准备它,在显示时调用cell.lblDescription.yourPropertyInModelObjectThatContainsAttributedString。明白了吗? - NeverHopeless
我也是这样做的,但不起作用。请帮帮我 @NeverHopeless - Vinod Kumar
@VinodKumar,请检查我的编辑后的答案是否对您有帮助?另外,当您注释掉这一行代码 cell.lblDescription.setHTMLFromString(htmlText: model.strItineraryDescription) 时会发生什么?它是否按预期工作? - NeverHopeless
你编辑后的答案对我有用,谢谢 @NeverHopeless - Vinod Kumar

1

你需要使用调度队列(Dispatch queue)

DispatchQueue.global(qos: .background).async {
    print("This is run on the background queue")
    let strmy = model.strItineraryDescription.html2AttributedString            

    DispatchQueue.main.async {
        cell.lblDescription.attributedText = strmy

    }
}

现在我的单元格高度没有增加,我正在使用预估高度。@KKRocks tblView.estimatedRowHeight = 185.0 tblView.rowHeight = UITableViewAutomaticDimension - Vinod Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接