title: Smooth UITableView Cell Expansion With Accordion Style
body: <p>My table view can expand and collapse cells when they are pressed, but the content that appears when the cell expands loads before the animation is finished.</p>
  
  <p>What I am left with is this:</p>
  
  <p><a href="https://i.stack.imgur.com/w7zXP.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/w7zXP.gif" alt="UITableView accordion expansion"></a></p>
  
  <p>What I would like it to look like is <a href="https://www.youtube.com/watch?v=u34Fw9biD3k&amp;feature=youtu.be" rel="nofollow noreferrer">this example</a>. This content appears as if it were behind a curtain and the cell expansion animation just reveals it.</p>
  
  <p>Here is the code that controls the table view:</p>
  
  <pre><code>class HistoryViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
  
      var expandedIndexPath: NSIndexPath? // Index path of the cell that is currently expanded
      let collapsedHeight: CGFloat = 44.0 // Constant to set the default collapsed height
      var ticketHistoryService = TicketHistoryService() // Service to gather info about Ticket History CoreData
  
      var tickets = [Ticket]()
  
      @IBOutlet var tableView: UITableView!
  
      override func viewDidLoad() {
          super.viewDidLoad()
  
          // Remove any appended table view cells
          tableView.tableFooterView = UIView()
  
          self.tickets = self.ticketHistoryService.fetchData() // Load inital data
  
      }
  
      // MARK: - Table View Methods
  
      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
          return self.tickets.count
      }
  
      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -&gt; UITableViewCell {
  
          let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! HistoryTableViewCell
  
          let ticket = self.tickets[indexPath.row]
  
          cell.titleLabel!.text = ticket.ticketNumber
          return cell
      }
  
      func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
          if editingStyle == .Delete {
              self.ticketHistoryService.removeObject(indexPath.row)
              self.tickets = self.ticketHistoryService.fetchData()
              tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
          }
      }
  
      func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
          self.tableView.beginUpdates()
          let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! HistoryTableViewCell
          if indexPath.isEqual(self.expandedIndexPath){ // If currently selected cell was just previously selected
              self.expandedIndexPath = nil
              cell.commentLabel.hidden = true
          }
          else {
              self.expandedIndexPath = indexPath
              cell.commentLabel.hidden = false
          }
          self.tableView.endUpdates()
      }
  
      func tableView(tableView: UITableView, willDeselectRowAtIndexPath indexPath: NSIndexPath) -&gt; NSIndexPath? {
          let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! HistoryTableViewCell
          cell.commentLabel.hidden = true
          return indexPath
      }
  
      func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -&gt; CGFloat {
          if indexPath.isEqual(self.expandedIndexPath) {
              return UITableViewAutomaticDimension
          }
          return collapsedHeight
      }
  }
  </code></pre>