【问题标题】:Invalid Update When adding Rows to UITableView向 UITableView 添加行时更新无效
【发布时间】:2015-05-08 03:26:21
【问题描述】:

无效更新:第 0 节中的行数无效。 更新 (5) 后包含在现有节中的行必须是 等于该节之前包含的行数 update (1),加上或减去插入或删除的行数 该部分(插入 1 个,删除 0 个)并加上或减去数量 移入或移出该部分的行(0 移入,0 移出)。

我正在尝试在用户点击一行时将行添加到表格视图中,以创建可展开的部分,但是在 Xcode 尝试添加它们之前不会计算额外的行,因此会导致此错误 (我想)。谁能指出我正确的方向?

// sectionExpanded is set to false in viewDidLoad. It is set to true when
// the user taps on the expandable section (section 0 in this case)

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0 && sectionExpanded {
        return 5
    } else {
        return 1
    }
}

// This should recount the rows, add the new ones to a temporary array and then add
// them to the table causing the section to 'expand'.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let selectedItem = menu[indexPath.row]
    let cell = tableView.cellForRowAtIndexPath(indexPath) as MenuCell
    if indexPath.section == 0 {
        var rows: Int
        var tmpArray: NSMutableArray = NSMutableArray()

        sectionExpanded = !sectionExpanded
        rows = tableView.numberOfRowsInSection(0)

        for i in 1...rows {
            var tmpIndexPath: NSIndexPath
            tmpIndexPath = NSIndexPath(forRow: i, inSection: 0)

            tmpArray.addObject(tmpIndexPath)
        }

        if !sectionExpanded {
            tableView.deleteRowsAtIndexPaths(tmpArray, withRowAnimation: UITableViewRowAnimation.Top)
        } else {
            tableView.insertRowsAtIndexPaths(tmpArray, withRowAnimation: UITableViewRowAnimation.Top)
        }
    } else {
        delegate?.rightItemSelected(selectedItem)
    }
}

【问题讨论】:

    标签: ios objective-c xcode uitableview swift


    【解决方案1】:

    它告诉您您正在尝试插入 1 个新行,但 numberofrows 应该是 5,之前是 1,而您正在尝试插入 1 个新行,即 2。这是您的问题。

    rows = tableView.numberOfRowsInSection(0) //this returns 1
    for i in 1...rows { //
        var tmpIndexPath: NSIndexPath
        tmpIndexPath = NSIndexPath(forRow: i, inSection: 0)
    
        tmpArray.addObject(tmpIndexPath)//this will contain only 1 object, because the loop will run only for 1 cycle
    }
    

    编辑

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let selectedItem = menu[indexPath.row]
        let cell = tableView.cellForRowAtIndexPath(indexPath) as MenuCell
        if indexPath.section == 0 {
            var rows: Int
            var tmpArray: NSMutableArray = NSMutableArray()
    
            sectionExpanded = !sectionExpanded
            rows = 1
            if sectionExpanded {
                rows = 5
            }
    
            for i in 1...rows {
                var tmpIndexPath: NSIndexPath
                tmpIndexPath = NSIndexPath(forRow: i, inSection: 0)
    
                tmpArray.addObject(tmpIndexPath)
            }
    
            if !sectionExpanded {
                tableView.deleteRowsAtIndexPaths(tmpArray, withRowAnimation: UITableViewRowAnimation.Top)
            } else {
                tableView.insertRowsAtIndexPaths(tmpArray, withRowAnimation: UITableViewRowAnimation.Top)
            }
        } else {
            delegate?.rightItemSelected(selectedItem)
        }
    }
    

    由于您知道行数始终为 5 或 1,因此您可以尝试这样的操作。但是,这不是标准方法,我建议更改您的数据源数组。
    下面是一些如何做到这一点的示例:http://www.nsprogrammer.com/2013/07/updating-uitableview-with-dynamic-data.html 它适用于 Objective-C,但您将了解它的要点。

    【讨论】:

    • 当我更改部分中的数字或行时,它不应该得到更新吗?有什么办法可以保证更新吗?
    • @ChrisByatt 我用可能的解决方案更新了我的答案
    【解决方案2】:

    您可以尝试修改数据源,然后重新加载表。

    【讨论】:

      【解决方案3】:

      您应该在beginUpdates()endUpdates() 之间使用insertRowsAtIndexPaths... 等。 tableView 将收集beginUpdates() 之后的所有更改,然后在endUpdates() 之后连贯地应用它们。所以试试类似的东西:

      tableView.beginUpdates()
      if !sectionExpanded {
                  tableView.deleteRowsAtIndexPaths(tmpArray, withRowAnimation: UITableViewRowAnimation.Top)
              } else {
                  tableView.insertRowsAtIndexPaths(tmpArray, withRowAnimation: UITableViewRowAnimation.Top)
              }
      tableView.endUpdates()
      

      请记住,在调用endUpdates() 之后,节数和行数必须与您的模型一致。

      由于我不知道你的模型,这里是一个简单的例子:

      class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
      
          @IBOutlet weak var tableView: UITableView!
      
          var sectionExpanded: Bool = false {
              didSet {
                  if oldValue != sectionExpanded {
      
                      let expIndexes = map(0..<model.count) { r in
                          NSIndexPath(forRow: r, inSection: 0)
                      }
      
                      // Here we start the updates
                      tableView.beginUpdates()
                      switch sectionExpanded {
                      case false:
                          // Collapsing
                          tableView.deleteRowsAtIndexPaths(expIndexes, withRowAnimation: .Top)
                          tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Top)
                      default:
                          // Expanding
                          tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Top)
                          tableView.insertRowsAtIndexPaths(expIndexes, withRowAnimation: .Bottom)
                      }
                      // Updates ended
                      tableView.endUpdates()
                  }
              }
          }
      
          let model = ["foo", "bar", "zoo"]
      
          //MARK: UITableView DataSource
      
          struct TableConstants {
              static let sectionCellIdentifier = "SectionCell"
              static let expandedCellIdentifier = "ExpandedCell"
          }
      
          func numberOfSectionsInTableView(tableView: UITableView) -> Int {
              return 1
          }
      
          func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return sectionExpanded ? model.count : 1
          }
      
          func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
              switch sectionExpanded {
              case false:
                  let cell = tableView.dequeueReusableCellWithIdentifier(
                      TableConstants.sectionCellIdentifier,
                      forIndexPath: indexPath) as UITableViewCell
                  cell.textLabel?.text = "The Section Collapsed Cell"
                  return cell
              default:
                  let cell = tableView.dequeueReusableCellWithIdentifier(
                      TableConstants.expandedCellIdentifier,
                      forIndexPath: indexPath) as UITableViewCell
                  cell.textLabel?.text = "\(model[indexPath.row])"
                  cell.detailTextLabel?.text = "Index: \(indexPath.row)"
                  return cell
              }
          }
      
          func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
              sectionExpanded = !sectionExpanded
          }
      }
      

      请注意,我将表格更新移动到sectionExpandedobserver

      【讨论】:

      • 遗憾的是,它仍然只返回 1 行 = ..etc
      【解决方案4】:

      section = 0 中已有 1 行,并尝试插入 5 个新行。您只能再添加 4 行以使用 numberOfRowsInsection 进行映射。

      试试下面的代码:

          sectionExpanded = !sectionExpanded
          rows = self.numberOfRowsInSection(0)-1
      
          for i in 1...rows {
              var tmpIndexPath: NSIndexPath
              tmpIndexPath = NSIndexPath(forRow: i, inSection: 0)
      
              tmpArray.addObject(tmpIndexPath)
          }
      

      【讨论】:

      • 那不是真的,他并没有尝试插入 5 个新行,但它清楚地表明他正在插入 1。检查我的答案以了解他的代码在做什么
      • sectionExpanded = !sectionExpanded 这改变了游戏规则!
      猜你喜欢
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-15
      • 2021-06-16
      • 1970-01-01
      • 2013-07-28
      • 2020-03-04
      • 1970-01-01
      相关资源
      最近更新 更多