Search code examples
iosuitableviewswift3nsattributedstringsmooth-scrolling

UITableView scrolling not smooth due to NSAttributedString


I am using NSAttributedString for converting html string to attributedString. I have converted it but label in cell so i have write below code in cellForRowAtIndex,when i apply this code tableview not scrolling smooth . If i remove this with simple text it scrolling smoothly .

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

I have convert html string to attributed string

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
    }

}

My html string is

<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>

Solution

  • What does this html2AttributedString do ? Does it convert HTML to attributed string on the fly on cellForRowAtIndexPath ? If yes, this is what actually taking time. Can we compromise on memory to speed up by cache the HTML's equivalent attributed string in another variable in the model. So this way on reloading it will fetch the prepared attributed string during either cell creation or reuse.

    e.g., Psuedocode:

    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.
      ...
    }
    

    Hope that helps!

    EDIT:

    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()
       ...
    }