title: UICollectionView laggy/choppy scrolling from NSAttributedString image
body: <p>I'm making a simple app that allows a user to write a sentence or two about their day everyday.</p>
  <p>I have a UICollectionView to display each individual day as a cell. In that cell, there is a UITextView where the user enters their text. Their entered text is saved in Core Data.</p>
  <p>Each cell populates the UITextView with the user's entered text (fetched from Core Data). But if the user hasn't entered text for that day, then the UITextView is populated with an NSAttributedString that has an image and a string in it to encourage the user to enter text.</p>
  <p>The problem is that the cells with the NSAttributedString cause the CollectionView scroll to be very laggy and choppy.</p>
  <p>The specific thing causing the lag is the image within the NSAttributedString. The image is from xcassets.</p>
  <p><strong>So how can I use the same image (in an NSAttributedString) on multiple cells and not have laggy scrolling?</strong></p>
  <h2>Possible solutions I've encountered:</h2>
  <ol>
  <li><em><strong>Prefetch or load the image asynchronously</strong></em> But my image is in xcassets. Isn't async loading for when you're fetching/download images from somewhere?</li>
  <li><em><strong>Cache the image</strong></em> But how would you cache an image from xcassets?</li>
  </ol>
  <h1><strong>ViewController.swift</strong></h1>
  <pre><code>    override func viewWillAppear(_ animated: Bool) {
           collectionView.delegate = self
           super.viewWillAppear(animated)
           collectionView.setNeedsLayout()
           collectionView.layoutIfNeeded()
      }
      
      func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -&gt; Int {
         return dates.count
      }
      
      func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -&gt; CGSize {
         let cellSize = CGSize(width: round(UIScreen.main.bounds.width * 0.8125), height: 469)
         return cellSize
      }
      
      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -&gt; UICollectionViewCell {
          let cell = collectionView.dequeueReusableCell(withReuseIdentifier: &quot;CollectionViewCell&quot;, for: indexPath) as! CollectionViewCell
          cell.fetchedResultsController = fetchedResultsController
          cell.date = dates[indexPath.item]
          return cell
      }
  </code></pre>
  <h1><strong>CollectionViewCell.swift</strong></h1>
  <pre><code>    @IBOutlet var textView: UITextView!
  
      var date = Date() {
         didSet {
           loadTextViewData()
         }
      }
  
      required init?(coder decoder: NSCoder) {
            super.init(coder: decoder)!
            self.setNeedsLayout()
            self.layoutIfNeeded()
      }
  
     func loadTextViewData(){
          let entity = CoreDataMethods.fetchEntity(date: date)
      
          if (entity != nil){
              textView.attributedText = NSAttributedString(string:entity?.value(forKey: &quot;textViewEntry&quot;) as! String)
          } else {
              loadPromptText()
          }
      }
  
      func loadPromptText(){
          let style = NSMutableParagraphStyle()
          style.lineSpacing = 10
          style.alignment = .center
          
          textView.attributedText = NSAttributedString(string: &quot;Tap here to enter!&quot; , attributes: [NSAttributedStringKey.paragraphStyle : style,  NSAttributedStringKey.font: UIFont(name: &quot;Helvetica-Bold&quot;, size: 16.0)!])
        
          let attributedString = NSMutableAttributedString(attributedString:textView.attributedText )
  
          let textAttachment = NSTextAttachment()
          textAttachment.image =  #imageLiteral(resourceName: &quot;EditIcon&quot;)
          textAttachment.image = UIImage(cgImage: textAttachment.image!.cgImage!, scale: CGFloat(7.0), orientation: .up)
  
          let attrStringWithImage = NSAttributedString(attachment: textAttachment)
          attributedString.append(attrStringWithImage)
  
          textView.attributedText = attributedString; 
      }
  </code></pre>