Reputation: 83
I have a food diary in my app that should be able to insert a row with information of the food the user has inputed. Everytime I try I get this error: "'NSInternalInconsistencyException', reason: 'attempt to insert row 3 into section 0, but there are only 2 rows in section 0 after the update'"
This is the ViewController code that performs the insert.
class FoodDiary: UITableViewController, AddRowDelegate {
var tableData = [[String: Any]]() //Datasource
func didAddRow(name: String, calories: String, section: Int) {
let getName = ["name":name, "calories":calories] as [String: Any]
tableData.append(getName)
let indexPath = IndexPath(row: tableData.count + 1, section: section)
tableView.insertRows(at: [indexPath], with: .automatic)
calsforToday.text = calories
tableView.reloadData()
}
This is my other ViewController that shows when the user is inputting the data with the protocol method.
protocol AddRowDelegate {
func didAddRow(name : String, calories : String, section : Int)
}
class PopupVC: UIViewController {
var delegate: AddRowDelegate?
var section: Int?
@IBOutlet weak var foodTimeLabel: UILabel!
@IBOutlet weak var foodPopup2: UIView!
@IBOutlet weak var foodPopUp: UIView!
@IBOutlet weak var inputFood: UITextField!
@IBOutlet weak var inputCals: UITextField!
@IBAction func saveToDiary(_ sender: Any) {
delegate?.didAddRow(name: inputFood.text!, calories: inputCals.text!, section: section!)
dismiss(animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "diaryEntry" {
if let selectedIndexPath =
tableView.indexPathForSelectedRow?.first{
let popVC = segue.destination as! PopupVC
popVC.delegate = self
if selectedIndexPath == 0 {
let label = "Add Breakfast"
popVC.foodLabel = label
popVC.section = 0
Pics of both VC's.
How can I get the row to insert with the information the user inputs?
Upvotes: 0
Views: 724
Reputation: 114865
As Dan said in a comment, you need tableData.count - 1
for your new index path row.
For example, if there are two elements in your array (count = 2) then you have rows 0 and 1 (i.e. count-1 is the last row).
func didAddRow(name: String, calories: String, section: Int) {
let getName = ["name":name, "calories":calories] as [String: Any]
tableData.append(getName)
let indexPath = IndexPath(row: tableData.count-1, section: section)
tableView.insertRows(at: [indexPath], with: .automatic)
calsforToday.text = calories
}
A couple of other points:
struct FoodItem {
var name: String
var calories: String // This should probably be an Int
}
class FoodDiary: UITableViewController, AddRowDelegate {
var tableData = Array(repeating: [FoodItem](), count: 3)
func numberOfSections(in tableView: UITableView) -> Int {
return self.tableData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData[section].count
}
func didAddRow(name: String, calories: String, section: Int) {
let newItem = FoodItem(name:name, calories:calories)
tableData[section].append(newItem)
let indexPath = IndexPath(row: tableData[section].count-1, section: section)
tableView.insertRows(at: [indexPath], with: .automatic)
calsforToday.text = calories
}
// Not shown; update your `cellForRow(at:)` to use the indexpath.section and row to get the required array and item.
}
Upvotes: 1