添加部分并出现错误:无效更新:部分数量无效

问题描述 投票:0回答:1

我正在应对 Big Nerd Ranch 的挑战,创建应用程序,添加随机项目,分为 2 个部分。当没有项目时,它应该显示“No Items”。

在初始阶段,我将其设置为具有标题为“无项目”的单个部分,并且在添加项目后,需要将其更新为标题为“50 及以下”和“超过 50”的两个部分。

添加项目时,我在

tableView.insertRows(at: [indexPath], with: .automatic)
方法内的
addNewItem
处抛出此错误。

我无法找出错误的根源 - 在调试时我可以清楚地看到,一旦触发

addNewItem
,部分就会更新为 2,然后作为添加新行流程的一部分(调用
tableView.insertRows(at: [indexPath], with: .automatic)
) )它会更新
numberOfSections
numberOfRowsInSection
,但在输入
cellForRowAt
之前会出错。因此,似乎所有先决条件都已正确更新,以便实际添加行内容。

ViewController 的完整代码如下或位于 GitHub 链接此处

线程1:“无效更新:节数无效。更新后表视图中包含的节数(2)必须等于更新前表视图中包含的节数(1),加上或减去插入或删除的节数(插入 0 个,删除 0 个)。表格视图: ;backgroundColor = ;图层 = ;contentOffset:{0, -59};contentSize:{393, 110};调整后的ContentInset:{59 , 0, 34, 0}; 数据源: >"

ItemsViewController:

import UIKit

class ItemsViewController: UITableViewController {
    // add ItemStore property to have access to store that holds all items
    var itemStore: ItemStore!
    var sections = 1

    @IBAction func addNewItem(_ sender: UIButton){
        let newItem = itemStore.createItem()
        sections = 2
        if newItem.valueInDollars > 50 {
            if let index = itemStore.itemsOverFifty.firstIndex(of: newItem){
                let indexPath = IndexPath(row: index, section: 1)
                tableView.insertRows(at: [indexPath], with: .automatic)
            }
        } else {
            if let index = itemStore.itemsFiftyAndUnder.firstIndex(of: newItem){
                let indexPath = IndexPath(row: index, section: 0)
                tableView.insertRows(at: [indexPath], with: .automatic)
            }
        }
    }

    @IBAction func toggleEditingMode(_ sender: UIButton){
        if isEditing{
            sender.setTitle("Edit", for: .normal)
            setEditing(false, animated: true)
        } else {
            sender.setTitle("Done", for: .normal)
            setEditing(true, animated: true)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // MARK: - Table view data source

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if sections == 1 {
            return "No Items!"
        }
        else if section == 0 {
            return "50 AND UNDER"
        } else {
            return "OVER 50"
        }
    }

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if sections == 1 {
            return 0
        } else {
            if section == 0 {
                return itemStore.itemsFiftyAndUnder.count
            } else {
                return itemStore.itemsOverFifty.count
            }
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
        let item = indexPath.section == 0 ? itemStore.itemsFiftyAndUnder[indexPath.row] : itemStore.itemsOverFifty[indexPath.row]

        cell.textLabel?.text = item.name
        cell.detailTextLabel?.text = "$\(item.valueInDollars)"

        return cell
    }

    // Override to support editing the table view.
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            let item = indexPath.section == 0 ? itemStore.itemsFiftyAndUnder[indexPath.row] : itemStore.itemsOverFifty[indexPath.row]
            itemStore.removeItem(item)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }
    }

    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to toIndexPath: IndexPath) {
        itemStore.moveItem(from: fromIndexPath.row, to: toIndexPath.row)
    }
}
ios swift uitableview
1个回答
0
投票

问题是您的表从 1 个部分开始,其中包含 0 个项目。在这种情况下,您会显示“无项目!”的部分标题。

第一次调用

addNewItem
时,您突然表现得好像表格视图始终有 2 个部分,并且根据需要将新项目添加到第 0 或 1 部分。这是表视图抛出错误的地方。在您尝试在两个部分之一插入 1 行之前,表认为它有 1 个部分有 0 行。将一行插入到一个部分后,您声明表视图有两个部分。但你从未告诉表视图添加第二部分。

第一次添加新项目时,您需要重写

addNewItem
的逻辑来添加新部分。

@IBAction func addNewItem(_ sender: UIButton){
    let newItem = itemStore.createItem()
    if (sections == 1) {
        // Tell the table about the new section and reload the first
        tableView.beginUpdates()
        sections = 2
        tableView.reloadSections(IndexSet(integer: 0), with: .fade)
        tableView.insertSections(IndexSet(integer: 1), with: .fade)
        tableView.endUpdates()
    } else {
        // The table already knows there are two sections, add the new row as needed
        if newItem.valueInDollars > 50 {
            if let index = itemStore.itemsOverFifty.firstIndex(of: newItem){
                let indexPath = IndexPath(row: index, section: 1)
                tableView.insertRows(at: [indexPath], with: .automatic)
            }
        } else {
            if let index = itemStore.itemsFiftyAndUnder.firstIndex(of: newItem){
                let indexPath = IndexPath(row: index, section: 0)
                tableView.insertRows(at: [indexPath], with: .automatic)
            }
        }
    }
}

根据您的需要,删除行时您可能需要反向功能。如果您删除最后一个项目并希望显示“无项目!”再次,您需要删除第 1 部分并重新加载第 2 部分,同时将

sections
从 2 重置回 1。


与您的问题无关,但值得指出 - 您不需要您的

toggleEditingMode
方法,也不需要您为其添加的按钮。相反,请使用
UIViewController
提供的内置编辑按钮。这假设您的表视图控制器位于
UINavigationController
中。

viewDidLoad
中您可以添加:

override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationItem.rightBarButtonItem = self.editButtonItem
}

editButtonItem
UIViewController
提供。它支持在“编辑”和“完成”之间切换视图控制器,并为您调用
setEditing(_:animated:)
。非常简单又容易。

© www.soinside.com 2019 - 2024. All rights reserved.