title: How to improve UITableView scrolling when data is calculated on the go in Swift?
body: <p>Before changes to the way we return cells in the <code>cellForRow:</code> method, I remember I would be able to check <code>if cell == nil</code>, and basically have two separate areas for cell-related-customization (properties that apply to all cells vs. only to some). However with <code>dequeueReusableCell:</code> I am unsure how to handle this and put it off until I was able to get all my cells populated properly -- but seemingly at the expense of a great amount of CPU and Memory usage. Here is my code in <code>cellForRow:</code> currently:</p>
  
  <pre><code>    if case (1...(days.count + 1), 2...(hours.count + 2)) = (indexPath.column, indexPath.row) {
  
              let cell = spreadsheetView.dequeueReusableCell(withReuseIdentifier: String(describing: ScheduleCell.self), for: indexPath) as! ScheduleCell
  
              let legs : NSArray = importedDict.object(forKey: "legs") as! NSArray
  
              print(hours![indexPath.row - 2])
  
              var profits : Array&lt;Double&gt; = []
  
              if let singleLegDict2 = legs as? [[String:AnyObject]] {
  
                  print (singleLegDict2)
                  for singleLegDict in singleLegDict2 {
                      let dict = singleLegDict as NSDictionary
  
                      let dateFormatter = DateFormatter()
                      dateFormatter.dateFormat = "yyyy-MM-dd"
                      let datee = dateFormatter.date(from: days![indexPath.column - 1] as! String)!
                      let datee2 = dateFormatter.date(from: dict.object(forKey: "expiry") as! String)!
  
                      let calendar = Calendar.current
  
                      // Replace the hour (time) of both dates with 00:00
                      let date1 = calendar.startOfDay(for: datee)
                      let date2 = calendar.startOfDay(for: datee2)
  
                      let components = calendar.dateComponents([.day], from: date1, to: date2)
                      let doub = Double(components.day!)
  
                      let years = doub * 0.00273972602
  
  //                    let under : NSNumber = dict.object(forKey: "underlying") as! NSNumber
                      let strike : NSNumber = dict.object(forKey: "strikePrice") as! NSNumber
                      let interest1 : NSNumber = dict.object(forKey: "interest") as! NSNumber
                      var interest2 = interest1 as! Double
                      interest2 = interest2/100
                      let userIV : NSNumber = NSNumber(value: Double(dict.object(forKey: "userIV") as! String)!)
                      var userIV2 = userIV as! Double
                      userIV2 = userIV2/100
  
                      var type = 0
                      if dict.object(forKey: "putCall") as! String == "CALL" {
                          type = 0
                      } else {
                          type = 1
                      }
  
                      let theo = getTheoreticalOptionPrice(forUnderlyingPrice: hours![indexPath.row - 2] as! NSNumber, withStrike: strike, withInterestRate: NSNumber(value: interest2), withVolatility: NSNumber(value: userIV2), withTimeToExpirationInYears: NSNumber(value: years), withType: NSNumber(value: type))
                      let userC : NSNumber = NSNumber(value: Double(dict.object(forKey: "userCost") as! String)!)
                      let quan : NSNumber = dict.object(forKey: "quantity") as! NSNumber
                      let diff = (theo - (userC as! Double)) * (quan as! Double)
                      print(theo, (userC as! Double))
                      profits.append(diff)
                  }
  
              }
  
              print(profits)
  
              var sumedArr : Double = profits.reduce(0, {$0 + $1}) as Double
              sumedArr = sumedArr * 100
  
              if sumedArr &lt; 0 {
                  cell.backgroundColor = UIColor(red: 0.8667, green: 0.1804, blue: 0.1804, alpha: 1.0)
  
              } else {
                  cell.backgroundColor = UIColor(red: 0.3843, green: 0.7686, blue: 0.1608, alpha: 1.0)
              }
  
              cell.label.text = String(format: "%.0f", sumedArr)
  
              return cell
          }
  </code></pre>
  
  <p>Any ideas on how to speed that up? Is the only way going to be preloading the data and then only referencing it in <code>cellForRow:</code>? How would I go about addressing this situation given the calculations I am doing per cell?</p>
  
  <p>I don’t need the cells to reload their data every time they are scrolled to. If all the cells load their data once when the view loads, and that data was just displayed — that would be perfect. </p>
  
  <p>With that in mind, I tried adding a check to see if the cell’s label was populated or not, and only if not, do all those calculations (assuming this would be the first loading of the table view). While that improved scrolling performance, the cells weren’t properly displaying and were completely out of order. Help?</p>
  
  <p><strong>Update:</strong> I have moved the heavy calculations to a background thread and now experience smooth scrolling. However, the cells still flicker because they are still regenerating their data each time they are shown. What is the easiest way to cache the cells so that they load once when the <code>tableView</code> is shown, and then scroll smoothly because they reference already loaded data?</p>