title: Dependency injection in uitableviewcell nibs
body: <p>I'm trying to build a pretty complex table. One cell of this table imports another table. In this imported table I show different rows depending on the situation. The imported table and all the importable table cells are organized into own nib files with own controllers for every cell. As a good programmer I'm trying to use dependency injection throughout the project. The problem now is that when I use the usual way of registering the nibs in viewDidLoad()</p>
  
  <pre><code>let cellNib = UINib(nibName: "BatchConsumptionCell", bundle: nil)
  tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionCell")
  </code></pre>
  
  <p>and then use them as dequeueReusableCell(withIdentifier: for:) in tableView(tableView: cellForRowAt:) </p>
  
  <pre><code>let batchConsumptionCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionCell", for: indexPath) as! BatchConsumptionCell
  batchConsumptionCell.setConsumption(consumption: consumption)
  return batchConsumptionCell
  </code></pre>
  
  <p>I'm not able to inject the dependencies in time.</p>
  
  <p>In the BatchConsumptionCell all I do in tableView(tableView: cellForRowAt:) works fine. This function is called after dequeueReusableCell(withIdentifier: for:) is executed. But as soon as I'm trying to make the tableView(tableView: numberOfRowsInSection:) dynamic I run into problems. This functions seems to be called before dequeueReusableCell(withIdentifier: for:) so the dependencies are not injected at this point.</p>
  
  <p>I tried to override the init(nibName: bundle:) initializer in my BatchConsumptionCell, but this is a UITableViewCell so I was not able to override this.</p>
  
  <p>How do I approach this? Is there any way I could inject the dependencies as the nib and its controller are initialized? Or do I organize my cells all wrong? Any ideas would be much appreciated.</p>
  
  <p>For more clarity here is my code:</p>
  
  <p><strong>ConsumptionDetailViewController</strong></p>
  
  <pre><code>import UIKit
  
  class ConsumptionDetailViewController: UITableViewController {
  
  // MARK: - Properties
  
  var moc: NSManagedObjectContext!
  
  var consumption: Consumption!
  
  
  // MARK: - Outlet Properties
  
  @IBOutlet weak var labelDate: UILabel!
  @IBOutlet weak var labelTime: UILabel!
  ...
  
  
  // MARK: - Default Methods
  
  override func viewDidLoad() {
      super.viewDidLoad()
  
      let cellNib = UINib(nibName: "BatchConsumptionCell", bundle: nil)
      tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionCell")
  
      updateTableFields(selectedConsumption: consumption)
  }
  
  
  // MARK: - UI Update Methods
  
  func updateTableFields(selectedConsumption: Consumption) {
  
      labelId.text = selectedConsumption.wtId
      ...
  }
  
  // MARK: - BatchAddEditDelegate Methods
  
  func didFinishEditing(consumption: Consumption) {
      updateTableFields(selectedConsumption: consumption)
  }
  
  // MARK: - TableView Methods
  
  override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -&gt; String? {
      ...
  }
  
  override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -&gt; CGFloat {
      ...
  }
  
  override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -&gt; CGFloat {
      ...
  }
  
  override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -&gt; CGFloat {
      ...
  }
  
  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
      if indexPath.section == 1 &amp;&amp; indexPath.row == 0 {
          let batchConsumptionCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionCell", for: indexPath) as! BatchConsumptionCell
          batchConsumptionCell.setConsumption(consumption: consumption)
          return batchConsumptionCell
      }
      return super.tableView(tableView, cellForRowAt: indexPath)
  }
  
  
  // MARK: - Navigation
  
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
      ...
  }
  
  }
  </code></pre>
  
  <p><strong>BatchConsumptionCell</strong></p>
  
  <pre><code>import UIKit
  
  class BatchConsumptionCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
  
  var consumption: Consumption!
  var batchConsumptionCount: Int!
  
  @IBOutlet weak var tableView: UITableView!
  
  override func awakeFromNib() {
      super.awakeFromNib()
  
      var cellNib = UINib(nibName: "BatchConsumptionBasicCell", bundle: nil)
      tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionBasicCell")
  
      cellNib = UINib(nibName: "BatchConsumptionMultiCell", bundle: nil)
      tableView.register(cellNib, forCellReuseIdentifier: "BatchConsumptionMultiCell")
  
      self.tableView.delegate = self
      self.tableView.dataSource = self
  }
  
  func setConsumption(consumption: Consumption) {
      self.consumption = consumption
      self.batchConsumptionCount = consumption.batchConsumptions?.count
  }
  
  func numberOfSections(in tableView: UITableView) -&gt; Int {
      return 1
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
      if batchConsumptionCount == 1 { // &lt;-- This does not work
          return 3
      } else {
          return batchConsumptionCount
      }
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
      if batchConsumptionCount == 1 { // &lt;-- This works fine
          let batchConsumptionBasicCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionBasicCell", for: indexPath) as! BatchConsumptionBasicCell
          let bc = consumption.batchConsumptions?.allObjects[0] as! BatchConsumption
          if indexPath.row == 0 {
              batchConsumptionBasicCell.configure(title: "Batch", detail: (bc.batch?.wtId)!)
          } else if indexPath.row == 1 {
              batchConsumptionBasicCell.configure(title: "Weight", detail: String(describing: bc.weight!))
          } else if indexPath.row == 2 {
              batchConsumptionBasicCell.configure(title: "Price", detail: String(format:"%.2f", bc.price))
          }
      } else if batchConsumptionCount &gt;= 2 {
          let batchConsumptionMultiCell = tableView.dequeueReusableCell(withIdentifier: "BatchConsumptionMultiCell", for: indexPath) as! BatchConsumptionMultiCell
          return batchConsumptionMultiCell
      }
      return UITableViewCell()
  }
  
  }
  </code></pre>
  
  <p>See the comments <code>// &lt;-- This works fine</code> and<br>
  // <code>&lt;-- This does not work</code> in BatchConsumptionCell</p>