0

I need to display Int in TableViewCell label to get sum the values. Here is my code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! BudgetTableViewCell
    
    let budgetEvent: BudgetModel
    budgetEvent = budgetList[indexPath.row]
  
    cell.nameEventLabel.text = budgetEvent.eventName
    cell.spentBudgetLabel.text = String(budgetEvent.spentBudget!)
    
    
    let totalSpent = budgetList.map{ $0.spentBudget! }.reduce(0, +)
    print("sum \(totalSpent)")
    return cell
}

When I run my app I have error message:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"

and the value is nil.

pkamb
  • 33,281
  • 23
  • 160
  • 191
AnDon
  • 11
  • 5
  • If your spentBudget is optional you need to provide a default value in case it is nil `budgetEvent.spentBudget ?? 0` – Leo Dabus Feb 16 '21 at 16:42
  • 3
    Does this answer your question? [What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – impression7vx Feb 16 '21 at 16:44
  • I call the `!` force unwrap operator the "crash if nil" operator. You should avoid it completely until you get really, really comfortable with optionals. – Duncan C Feb 16 '21 at 16:48

2 Answers2

2

You are trying to force unwrap your values which is not a good practice, as if the value is not present, your application fails/crashes.

The force unwrapping means that you use the ! operator to tell the compiler that you are sure that a value is there, and we can extract it. In the following lines you are using force unwrapping:

// 1
cell.spentBudgetLabel.text = String(budgetEvent.spentBudget!)
// 2
let totalSpent = budgetList.map{ $0.spentBudget! }.reduce(0, +)

It is hard to tell which one causes the error you have, but you can improve your code which will help you identify your problem:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "eventCell", for: indexPath) as! BudgetTableViewCell

    let budgetEvent = budgetList[indexPath.row]

    cell.nameEventLabel.text = budgetEvent.eventName
    if let spentBudget = budgetEvent.spentBudget {
        cell.spentBudgetLabel.text = String(spentBudget)
    } else {
        print("SpentBudget is empty")
    }

    let totalSpent = budgetList.compactMap{ $0.spentBudget }.reduce(0, +)
    print("sum \(totalSpent)")
    return cell
}

I replaced the map function with compactMap, which will return only the non-optional values. You can read about this here

πter
  • 1,899
  • 2
  • 9
  • 23
  • thank you. This was helpful. But now my labels are empty. Do I need get the values from Firebase in this function? If yes, can you help me how to get? – AnDon Feb 16 '21 at 22:08
  • You should get your values in an other function, where you download your data and when finished you reload your tableView. If you do not wan to see an empty tableView you can implement a load which is presented while downloading the data and is hidden when the download is complete. – πter Feb 16 '21 at 22:12
  • I had the values in functions. I think this works well, cus this "cell.nameEventLabel.text = budgetEvent.eventName" is displaying, but I don't know why the labels with Int values are empty. It's printing "} else { print("SpentBudget is empty")" – AnDon Feb 16 '21 at 22:28
  • From what you write, I think your "budgetEvent.spentBudget" is empty, you should double check that on the database side – πter Feb 17 '21 at 06:54
0

You can use like this,

cell.spentBudgetLabel.text = String(format: "%d", budgetEvent.spentBudget)
pkamb
  • 33,281
  • 23
  • 160
  • 191