如何在不调用 tableView.reloadData() 的情况下更新表视图单元格的 textView 标签

How to update table view cells' textView tags without calling tableView.reloadData()

提问人:michaelthedeveloper 提问时间:10/12/2020 更新时间:10/12/2020 访问量:80

问:

我有一个tableView控制器,它利用带有textViews的自定义单元格。目前,我有一个回调函数,因此每当用户在编辑 textView 时点击 return 时,就会在 tableView 中插入一个新单元格,并成为第一个响应者。为此,每当用户点击 return 时,我都会将 textView 的标签 + 1 存储在名为 cellCreatedWithReturn 的变量中,以便 tableView 知道将单元格插入到何处以及将哪个单元格作为第一响应者。问题在于,在重新加载 tableView 之前,最终会出现重复的 textView 标签。如果已经有一个标签为 5 的 textView,并且我在编辑标签为 4 的 textView 时按 return,它会创建另一个 textView 标签为 5 的单元格。现在,第一个标签 5 位于第 6 行,但由于它被标记为 5,因此点击 return 会导致单元格插入第 6 行而不是第 7 行。我尝试将回调更改为仅使用 indexPath.row 而不是 cellCreatedWithReturn 变量,但这会导致新单元格始终作为 tableView 中的最后一个单元格插入。我不想调用 tableView.reloadData(),因为这会导致键盘降低,然后在重新分配第一响应者时立即升高,这看起来不太好。我需要键盘保持升起。

这是我的shouldChangeTextIn,其中调用了回调:

var cellCreatedWithReturn: Int?
var returnKeyCallback: (()->())?

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if(text == "\n") {
        cellCreatedWithReturn = textView.tag + 1
        print(cellCreatedWithReturn!)
        returnKeyCallback?()
        return false
    } else {
        return true
    }
}

以及 cellForRowAt 中的回调函数:

self.returnKeyCallback = { [weak self] in
    if let self = self {
        let newRow = self.cellCreatedWithReturn! - 1
        // this is -1 because cell 0 is not included in the same data source
        do {
            try self.realm.write {
                self.song.lyrics.insert(LyricLine(), at: newRow)
            }
        } catch {
            print("Error when inserting new lyric line to song in Realm when return pressed")
        }
        let newIndexPath = IndexPath(row: self.cellCreatedWithReturn!, section: 0)
        print(newIndexPath.row)
        self.tableView.performBatchUpdates({
            self.tableView.insertRows(at: [newIndexPath], with: .automatic)
        }, completion: { b in
            guard let c = tableView.cellForRow(at: newIndexPath) as? newNoteTableViewCell else { return }
            c.lyricsField.becomeFirstResponder()
            c.lyricsField.tag = self.cellCreatedWithReturn!
            if indexPath.row > newIndexPath.row {
                cell.lyricsField.tag += 1
            }
        })
    }
}
iOS Swift UITableView 回调 TextView

评论

0赞 Andreas Oetjen 10/12/2020
您可以获取当前所选单元格的索引路径,然后在该路径下方添加一个新单元格,然后选择该新单元格(以及其中的文本字段),而不是将行信息存储在文本视图的标记中
0赞 michaelthedeveloper 10/12/2020
@AndreasOetjen 我在这种方法中遇到的问题是,点击单元格以编辑其 textView 不会选择该单元格。
0赞 Andreas Oetjen 10/12/2020
我知道。您需要(以编程方式)选择保存 textView 的单元格。
0赞 michaelthedeveloper 10/15/2020
@AndreasOetjen我明白了。在这种情况下,该怎么做呢?谢谢你的帮助。
0赞 michaelthedeveloper 10/15/2020
我想通了。我需要先在 UITextView 上禁用用户交互,然后在选择单元格时以编程方式启用它,并在下一行中分配第一个响应者。

答: 暂无答案