首页 > 解决方案 > 如何修复 Swift 中的“无法使单元格出列”错误

问题描述

我遇到了一些困难,并且无法在其他 SO 答案中找到任何解决方案......

我在一个视图控制器中有两个表视图,它们都可以很好地来回切换,但前提是首先加载其中一个。

当我尝试先加载另一个时(有时我会根据用户到表的路径来执行此操作),应用程序崩溃并出现错误“无法使具有标识符 customMessageCell 的单元格出列 - 必须注册一个 nib 或一个标识符的类或连接故事板中的原型单元“

我已经在 viewDidLoad 中为两个自定义单元格注册了笔尖,在情节提要中识别了原型单元格等。基本上,当我搜索此错误时,所有常用的解决方案

在我的 viewDidLoad 中:

messageTableView.register(UINib(nibName: "CustomMessageCell", bundle: nil), forCellReuseIdentifier: "customMessageCell")
listTableView.register(UINib(nibName: "ItemCell", bundle: nil), forCellReuseIdentifier: "itemCell")

另外,我有一个可以切换表格的枚举

switch currentTable {
case .list:
   tableSelected(table: "list")
case .notes:
   tableSelected(table: "notes")
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        switch currentTable {
        case .list:
            let cell = tableView.createCell(tableView: listTableView, indexPath: indexPath, itemArray: listArray)
            return cell
        case .notes:
            let cell = tableView.dequeueReusableCell(withIdentifier: "customMessageCell", for: indexPath) as! CustomMessageCell

            if messageArray.count == 0 {
                cell.messageBody.text = "No notes yet"
            } else {
                cell.messageBody.text = messageArray[indexPath.row].messageBody
                cell.senderUser.text = messageArray[indexPath.row].sender

                let user = cell.senderUser.text

                switch user {
                case "jeffrey@sandiegomentors.com":
                    cell.avatarImageView.image = UIImage(named: "team-4")
                case "djones219@pointloma.edu":
                    cell.avatarImageView.image = UIImage(named: "team-3")
                case "dave@sandiegomentors.com":
                    cell.avatarImageView.image = UIImage(named: "team-2")
                case "amirthought@gmail.com":
                    cell.avatarImageView.image = UIImage(named: "team-6")
                case "james@sandiegomentors.com":
                    cell.avatarImageView.image = UIImage(named: "team-1")
                default:
                    cell.avatarImageView.image = UIImage(named: "twitteregg")
                }

                if cell.senderUser.text == Auth.auth().currentUser?.email as String? {
                    cell.messageBackground.backgroundColor = #colorLiteral(red: 0.005996327382, green: 0.4056355059, blue: 0.8481400013, alpha: 1)
                } else {
                    cell.messageBackground.backgroundColor = #colorLiteral(red: 0.3254587054, green: 0.325510323, blue: 0.3254474401, alpha: 1)
                }

                if let timeStamp = messageArray[indexPath.row].time {
                    let date = Date(timeIntervalSince1970: timeStamp/1000)
                    let formatter = DateFormatter()
                    formatter.dateFormat = "MMM d, yyyy"
                    let dateString = formatter.string(from: date)
                    cell.timeLabel.text = dateString
                }
            }

            return cell
        }
func tableSelected(table: String) {
        if table == "list" {
            listTableView.isHidden = false
            messageTableView.isHidden = true
            messageInputView.isHidden = true
            addButton.isEnabled = true

            currentTable = .list

            buttonSelection(selected: tabButtons[1], unselected: tabButtons[0])

            buttonTodoWidthConstraint.isActive = true
            buttonNotesWidthConstraint.isActive = false

            listTableView.reloadData()

        } else {

            messageTableView.isHidden = false
            messageInputView.isHidden = false
            listTableView.isHidden = true
            addButton.isEnabled = false

            currentTable = .notes

            buttonSelection(selected: tabButtons[0], unselected: tabButtons[1])

            buttonNotesWidthConstraint.isActive = true
            buttonTodoWidthConstraint.isActive = false

            messageTableView.reloadData()
            scrollToBottom()
        }
    }

当我运行应用程序并将初始 currentTable 作为 .list 时,我可以在两者之间切换(通过一个切换枚举值的按钮),并且它按预期工作。

当我将初始 currentTable 作为 .notes 时,它会立即崩溃。

有任何想法吗?

提前致谢

标签: iosswiftuitableview

解决方案


如果即使每个表都注册了其适当的单元格标识符,但您仍收到“无法使单元格出队”错误,这意味着您可能在为另一个表cellFor调用时为一个表实例化了一个单元格。当您有一组UITableViewDataSource方法为两个表提供服务时,这很容易做到。您可以通过在 中添加断点来确认这一点cellFor,将tableView传递给该方法的值与您的两个出口进行messageTableView比较listTableView: 确保您正在实例化适合该表的单元格。

我建议不要依赖,而是检查以cellFor确定要实例化哪种类型的单元格。那么根本不可能实例化错误的单元格。你甚至可以完全消除。currentTabletableViewcurrentTable

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch tableView {
    case messageTableView:
        ...

    case listTableView:
        ...

    default:
        fatalError()
    }
}

坦率地说,我不鼓励将一个UITableViewDataSource用于两个不同的表。另一种方法是将 for each 封装UITableViewDataSource到它自己的对象中,这样就不可能为给定的表实例化错误的单元格。它还有助于缓解视图控制器膨胀。


推荐阅读