1

I have a generic cell ItemCell that can display any kind of item. The descendant of my Item class is my Armor class. I have a function inArmor that overrides a function in Itemthat returns an ItemCell. However no matter what label, when I try to change the text value of one I get the error below. I can't even set a hard coded string. I also checked the ItemCell class and it's .xib file and everything is linked. Is there something I'm missing? Let me know what code you would need to see as I have no idea where this issue is coming from.

fatal error: unexpectedly found nil while unwrapping an Optional value

CharacterTableView.swift

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(UINib(nibName: "ItemCell", bundle: nil), forCellReuseIdentifier: "ItemCell")
switch sections[indexPath.section] {
case "Equipped":
  return Character.inventory.equippedGear[indexPath.row].cell
case "Armor":
  return Character.inventory.unequippedArmor[indexPath.row].cell
case "Weapons":
  return Character.inventory.unequippedWeapons[indexPath.row].cell
case "Healing":
  return Character.inventory.healingItems[indexPath.row].cell
default:
  return ItemCell()
}
}

Armor.swift

override var cell: ItemCell {
    let cell = ItemCell()
    cell.name.text = "Name"
}

ItemCell.swift

class ItemCell: UITableViewCell {
  //MARK: - IBOutlets
  @IBOutlet weak var imageItem: UIImageView!
  @IBOutlet weak var name: UILabel!
  @IBOutlet weak var imageStat1: UIImageView!
  @IBOutlet weak var labelStat1: UILabel!
  @IBOutlet weak var imageStat2: UIImageView!
  @IBOutlet weak var labelStat2: UILabel!
}
Austin E
  • 823
  • 1
  • 9
  • 22
  • paste your code please. The error itself means some where you have an *optional* which it's `nil`. Also see [here](http://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – mfaani Feb 23 '17 at 20:57
  • Hi Austin, I would like to understand what type of table view you are using, dynamic prototypes or static cells. I also would like to understand the function that returns an ItemCell and the relation it has with the datasource method tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell – MacUserT Feb 23 '17 at 21:13
  • @MacUserT I'm using the plain `UITableViewController`. My understanding of it is that it is a dynamic prototype, however rather than be connected to the table view in the storyboard it is in it's own xib file. As for the relationship between the function that returns the cell. It creates a `ItemCell` object, uses the properties in it to set the values(This is where it is crashing) and returns the object. I did this to make the code that edits the cell more reusable. So my `cellForRowAt` determines which item should be at the row and then directly returns the `ItemCell` object. – Austin E Feb 23 '17 at 21:18
  • Hi Austin, although I understand your concept, I can't give you any help in why your code is finding a nil while unwrapping an optional value. In most cases the error message also gives a hint where the failure occurred. – MacUserT Feb 23 '17 at 21:35
  • @MacUserT Ive added excerpts of code above that I thought were relevant. Please let me know if this isn to enough. – Austin E Feb 24 '17 at 02:14

2 Answers2

0

I see several potential problems in your code that can cause the crash.

  1. You register your cell in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell, but you don't dequeue a cell. This looks to me as that you are returning a cell that has no relation to the tableview that is requesting the cell.
  2. You have a UITableViewCell with many outlets, but you don't set these outlets anywhere. This means that all the outlets except the name will be nil and be explicitly unwrapped (because of the !) when displayed in the table view.
  3. You switch on indexPath. section and assumes there the sections are Strings that you have defined. I can't check whether this is the case and if the datasource call really comes with the stings as section. Have your checked this while debugging?
  4. As a default you bluntly return an empty ItemCell. By empty I mean that none of the outlets are set and therefor empty. The labels are explicitly unwrapped (because of the !) and will make your app crash.

I hope this helps you solve the problem.

MacUserT
  • 1,760
  • 2
  • 18
  • 30
0

To create cells for a table, you should be calling something like…

tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell

Also, you might find it better to use an enum than an array of Strings for your sections:

enum Sections: Int {
    equipped, armour, weapons, healing
}

And your cell should be registered just once. So…

enum Sections: Int {
    equipped, armour, weapons, healing
}

override func viewDidload() {
    super.viewDidLoad()

    tableView.register(UINib(nibName: "ItemCell", bundle: nil), forCellReuseIdentifier: "ItemCell")
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as! ItemCell

    guard let section = Section(rawValue: indexPath.section) else {
        return cell
    }

    switch section {
    case .equipped:
      cell.item = Character.inventory.equippedGear[indexPath.row]
    case .armour:
      // etc
    case .weapons:
      // etc
    case .healing:
      // etc
    }
    return cell
}
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160