title: (Swift) How to pass data back and forth between UITableView and UITableViewCell?
body: <p>I'm a beginning iOS developer and I've been stuck on an issue for quite some time now.</p>
  
  <p><strong>Background:</strong>
  I have a single viewcontroller in which I have placed a TableView (I cannot use a tableviewcontroller). It holds 4 dynamic prototype cells:
  Cell 1 has an UITextField and a couple of labels, Cell 2-4 only have a label (with different types of information) and have to be hidden initially.</p>
  
  <p>When an user enters a number (max. 3 digits) in the UITextField of the first cell, the number has to be compared to check if it is a correct/existing number. If this number proves correct, 2 things will have to happen: 1) the labels in the first cell will need to change layout (colour, font, size, ...) and set the data of one label. 2) the other cells in the tableview will have to appear beneath the first cell.</p>
  
  <p><strong>Problem:</strong> 
  I'm having trouble sending data back and forth between the first UITableViewCell and its UITableView. For the text input I use the shouldChangeCharactersInRange method in the cell class, which then limits the # of digits and calls a method in the tableView class where the data will be compared. For this I used delegation.</p>
  
  <p>However, after checking whether the number is a match, I need to call a method in the cell class (from within the tableview class) that will change the layout and set the data of a label in the cell. Yet I can't seem to figure out a way to make this method call work and access the outlets.</p>
  
  <p><strong>Summarised:</strong> cell class sends number to tableview class, methods in tableview class run, tableview class sends bool to cell class where outlets need to be changed.</p>
  
  <p><strong>What I tried:</strong> 
  I tried setting up delegation in the other direction, but it wouldn't trigger. Using a normal method call wouldn't work either, because then the outlets are nil.</p>
  
  <p>I believe my problem lies in the fact that I need to reference the same instance/object of the cell to access the outlets?</p>
  
  <p>I selected and simplified the relevant pieces of code:</p>
  
  <p><strong>1) TableView class</strong></p>
  
  <pre><code>class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, updateUITableView {
  
  var existingNumber = 200
  var cellsRowHeight = false
  
  @IBOutlet var tableView: UITableView!
  
  //Started by InputTableViewCell when UITextField has a 3 digit-number
  func checkNumberInput(inputNumber: Int) {
      //Step 1: check if the number matches an existing one
      let match = checkNumberMatch(inputNumber: inputNumber)
  
      //Step 2: send a bool back to the cell class to change the layout through outlets
      InputTableViewCell().changeLayout(numberMatch: match) // &lt;--- problem
  
      //Step 3: make the hidden cells appear
      toggleCellsVisibility(numberMatch: match)
  }
  
  //Step 1
  func checkNumberMatch(inputNumber: Int) -&gt; Bool {
      if inputNumber == existingNumber {
          return true
      } else {
          return false
      }
  }
  
  //Step 2
  func toggleCellsVisibility(numberMatch: Bool) {
      cellsRowHeight = numberMatch
      if numberMatch == true { //cells appear
          tableView?.beginUpdates()
          tableView?.endUpdates()
          //possible additional code
      } else { //cells dissappear
          tableView?.beginUpdates()
          tableView?.endUpdates()
          //possible additional code
      }
  }
  
  //Step 3
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -&gt; CGFloat {
      switch (indexPath.row) {
      case 0 where !cellsRowHeight || cellsRowHeight:
          return 170
      case 1 where !cellsRowHeight:
          return 0
      case 1 where cellsRowHeight:
          return 54
      //cases for other cells to appear/dissappear
      default:
          return 44
      }
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
      if indexPath.row == 0 {
          //Create tableViewCell
          let cellIdentifier = "InputCell"
          let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! InputTableViewCell
  
          cell.delegate = self
  
          //Customize lay-out of cell
          cell.preservesSuperviewLayoutMargins = false
          cell.separatorInset = UIEdgeInsets.zero
          cell.layoutMargins = UIEdgeInsets.zero
  
          return cell
      }
      //creation of other cells
  }
  
  // MARK: - Loading
  override func viewDidLoad() {
      super.viewDidLoad()
      tableView.tableFooterView = UIView(frame: CGRect.zero)
  }}
  </code></pre>
  
  <p><strong>2) Cell class:</strong></p>
  
  <pre><code>protocol updateUITableView: class {
  func checkNumberInput(inputNumber: Int)
  }
  
  class InputTableViewCell: UITableViewCell, UITextFieldDelegate {
  var delegate: updateUITableView?
  
  @IBOutlet var textField: UITextField!
  @IBOutlet var letterLabel: UILabel!
  
  //Step 2: problem!
  func changeLayout(numberMatch: Bool) {
      if numberMatch == true {
          print("Success") //this line triggers
          letterLabel?.text = "A" //is nil
          //other lay-out changes
      }
      else {
          print("Fail, please provide an existing number")
          //other lay-out changes
      }
  }
  
  //Set maximum character limit in textField and dismiss keyboard when character limit is reached.
  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -&gt; Bool {
      let currentCharacterCount = textField.text?.characters.count ?? 0
      let newLength = currentCharacterCount + string.characters.count - range.length
  
      if (newLength == 3) {
          textField.text = (textField.text! as NSString).replacingCharacters(in: range, with: string)
  
          //Get text from textField
          let numberInput: Int? = Int(textField.text!)
          if numberInput != nil {
              delegate?.checkNumberInput(number: numberInput!) //send number to tableview class
          }
          //Dismiss keyboard
          textField.resignFirstResponder()
  
          if (range.length + range.location &gt; currentCharacterCount) {
              return false
          } else {
              return true
          }
      }
      return true
  }
  
  func viewDidLoad() {
  }}
  </code></pre>
  
  <p>The actual problem is situated in "Step 2". Using this method I can perform the print statement, but the actual labels/outlets are nil because it is just a generic call.</p>
  
  <p>Any help would be immensely appreciated! Thank you!</p>