iOS:无效更新:第n

时间:2018-04-08 15:10:42

标签: ios swift uitableview

我正在构建一个iOS应用程序,基本上用户通过按下" +"来创建项目。按钮,然后应用程序应根据项目的位置将新项目放在表格的相应部分。但是我收到错误:无效更新:第1节中的行数无效。更新(1)后现有部分中包含的行数必须等于更新前该部分中包含的行数。这是我的代码,谢谢

let sections = ["Bathroom", "Bedroom", "Dining Room", "Garage", "Kitchen", "Living Room"]

@IBAction func addNewItem(_ sender: UIBarButtonItem) {
    /*
    //Make a new index path for the 0th section, last row
    let lastRow = tableView.numberOfRows(inSection: 0)
    let indexPath = IndexPath(row: lastRow, section: 0)

    //insert this new row into the table
    tableView.insertRows(at: [indexPath], with: .automatic)*/

    //Create a new item and add it to the store
    let newItem = itemStore.createItem()
    var Num: Int = 0

    if let index = itemStore.allItems.index(of: newItem) {
        switch newItem.room {
        case "Bathroom":
            Num = 0
            print("I am in here")
        case "Bedroom":
            Num = 1
        case "Dining Room":
            Num = 2
        case "Garage":
            Num = 3
        case "Kitchen":
            Num = 4
        case "Living Room":
            Num = 5
        default:
            Num = 0
            print("I am in Default")
        }
        let indexPath = IndexPath(row: index, section: Num)
        tableView.insertRows(at: [indexPath], with: .automatic)
    }

override func numberOfSections(in tableView: UITableView) -> Int {
    return sections.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return itemStore.allItems.count

}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //create an instance of UITableViewCell, with default appearance
    //let cell = UITableViewCell(style: .value, reuseIdentifier: "UITableViewCell")

    //get a new or recycled cell
    //if indexPath.row < itemStore.allItems.count {

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

        //Set the text on the cell with the decription of the item
        //that is at the nth index of items, where n = row this cell
        //will appear in on the table view
        let item = itemStore.allItems[indexPath.row]

        if item.name == "" {
            cell.nameLabel.text = "Name"
        } else {
            cell.nameLabel.text = item.name
        }

        if item.serialNumber == nil {
            cell.serialNumberLabel.text = "Serial Number"
        } else {
            cell.serialNumberLabel.text = item.serialNumber
        }
        cell.valueLabel.text = "$\(item.valueInDollars)"
        cell.roomLabel.text = item.room

        if item.valueInDollars < 50 {

            cell.valueLabel.textColor = UIColor.green

        }else if item.valueInDollars >= 50 {

            cell.valueLabel.textColor = UIColor.red
        }

        cell.backgroundColor = UIColor.clear
        return cell
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let LocationName = sections[section]
    return LocationName
}

非常感谢您的时间!

这就是我创建项目的方式

 @discardableResult func createItem() -> Item {
    let newItem = Item(random: false)

    allItems.append(newItem)

    return newItem
}

3 个答案:

答案 0 :(得分:0)

问题是您应该首先在数组中插入项目:

itemStore.allItems.append(newItem)

此外,numberOfRowsInSection中的部分和行之间存在差异(每个部分的返回行数),您有一个返回相同数字的开关,它应该是

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     return itemStore.allItems.count
}

修改:

问题是当表加载时所有部分都有0行(itemStore.allItems.count为零),当你尝试在第0部分第0行插入一行时 - 必须仅更新dataSource对于那个部分,这在你的情况下不会发生,因为它是为所有部分返回的相同数组,所以你必须有一个数组数组,其中内部数组代表行数,所以从中添加/删除它不会#39; t影响其他的,,,,,或将插入锁定为像这样的第0部分

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

   if (section  == 0 ) { 
       return itemStore.allItems.count
   }
   return 0 
}

在这个编辑中我插入了2个0和2部分而没有崩溃,因为我处理numberOfRowsInSection以返回旧部分的旧数字,为什么能够在所有部分插入,你必须有一个不同的数据源数组或者从numberOfRowsInSection进行管理,请参阅此处的编辑演示Homepwner

而不是在viewDidLoad中设置页脚实现此方法

override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {

    if(section == 5 ) {
        let textLabel = UILabel()
        textLabel.text = "No more Item"
        return textLabel
    }

    return nil
}

答案 1 :(得分:0)

您的数据源存在严重问题。所有部分的numberOfRow都相同。即 itemStore.allItems.count 。这意味着您在每个部分中设置相同的行数 主要问题是,在添加新项目时,您将在特定部分插入新行,这意味着

  

section的新行数= section +中的前一行数   1

但是,数据源中没有添加内容。

因此,根据代码,您已插入一个新行,但由于您未在此处添加项目,因此您的数据源只有一个记录。

所以我希望您按照以下步骤执行以下操作:

  
      
  1. 在所需数据源中添加项目。
  2.   
  3. inserRowInSection
  4.   

更新删除cellForRowAtIndexPath 中的条件:

if indexPath.section <= 1 ,它阻止了。你不需要那个。如果节的数量小于1,则不会调用它。此外,它是 else 块,它一直被调用,因为您的代码中已有部分。所以如果案例永远不会被调用。

所以我遇到了这个问题。在itemStore.createItem()中,会议室的值始终为会议室。在 switch-case 中,您永远不会有 Room case 。所以它总是属于默认情况。你需要解决这个问题。

答案 2 :(得分:0)

@ Jacky.S我下载你的代码并尝试调试它.Fist正确查看我们的错误。

reason: 'Invalid update: invalid number of rows in section 1.  The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (0)

所以它在更新之前说过,sections0 rows。现在,您尝试使用此代码更新tableview

print(indexPath)
tableView.insertRows(at: [indexPath], with: .automatic)

我刚刚添加了print语句以进行调试,并打印[0, 0]。因此,您将表视图显示为insert 0th row on section 0。 现在当您向row插入任何tableview时,它会调用delegate方法。现在请看下面的委托方法。

override func tableView(_ tableView: UITableView, numberOfRowsInSection 
  section: Int) -> Int {
    if section == 0{
        print("0",itemStore.allItems.count)
    }
    if section == 1{
        print("1",itemStore.allItems.count)
    }
   // print(itemStore.allItems)
        return itemStore.allItems.count
}

在您的代码中,您只需return itemStore.allItems.count。我添加了上述代码进行调试。现在看来itemStore.allItems.count始终返回1.因此,首先section它完美无缺因为很少时候你在row中插入了section,其索引是[0 =行,0 =部分]。所以你先前为rows返回的section 0等于最近为rows返回section 0。但是,section 1之前return no row表示您的section 1之前没有rows但是在上面的委托方法中,您还会为第1部分返回1 row。因为之前您从未updatereturn任何rows第1部分。这就是您编码的原因crash并说出

your number of rows contained in an existing section after the update is 1 which must be equal to the number of rows contained in that section before the update. Which is 0.

所以这就是你崩溃的原因。

现在,要从崩溃中恢复,allItems应该是dictionaryarray of array

var allItems = [[Item]]()

var allItems = ["String":[Item]]()

allItems元素是这样的

allItems = ["bathroom":[item1, item2, item3],"bedroom":[item1, item2, item3, item4]]

所以这里有2个部分,一个是bathroom,另一个是bedroom。第一部分有3 row,第二部分有4 row,在你的tableview委托方法中你有return 3的{​​{1}}和section 0的{​​{1}}