UITableView单元格在当前视图之外时不会成为第一个响应者

lfapxunr  于 2022-09-19  发布在  Swift
关注(0)|答案(1)|浏览(138)

我有一个显示待办事项的TableViewController。在控制器中,我制作了一个按钮,当按下该按钮时,将在底部创建一个新的TableViewCell,它与其他元素一起具有UITextView

到目前为止,这就是我所能做到的-

  • 点击按钮后创建新单元格
  • 使新创建的单元格的文本视图成为第一响应者

然而,从我观察到的情况来看,除了表格中的最后一个单元格不可见(即它在框架下方)之外,一切都运行得很好。在这种情况下,单元格被创建,但没有被创建,第一响应者或其他单元格的文本视图获得光标。

请参见此处的输出-https://drive.google.com/file/d/1mRN8MEO5HBJ3ICUiRE0Yc4ib8tp62MYc/view?usp=sharing

代码是这样的-

import UIKit

class TableViewController: UITableViewController, InboxCellDelegate {

    var cell = InboxCell()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
//         self.navigationItem.leftBarButtonItem = self.editButtonItem

        tableView.register(UINib(nibName: "InboxCell", bundle: nil), forCellReuseIdentifier: "InboxCell")
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 50
    }

    @IBAction func inboxAddPressed(_ sender: UIBarButtonItem) {

        addRowToEnd()

    }

    func addRowToEnd() {

        Task.tasks.append("")

        tableView.beginUpdates()
        tableView.insertRows(at: [IndexPath(row: Task.tasks.count - 1, section: 0)], with: .automatic)
        tableView.endUpdates()

        cell.inboxTaskTextView.becomeFirstResponder()

    }

    func didChangeText(text: String?, cell: InboxCell) {
        self.tableView.beginUpdates()
        self.tableView.endUpdates()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows

        return Task.tasks.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

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

        // Configure the cell...
        cell.delegate = self

        cell.inboxTaskTextView.text = Task.tasks[indexPath.row]

        return cell
    }

    // Override to support conditional editing of the table view.
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.

        return true
    }

    // Override to support editing the table view.
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == .delete {
            tableView.beginUpdates()
            Task.tasks.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .automatic)
            tableView.endUpdates()
        }

    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

}

我试着先滚动到表格的底部,然后让新创建的单元格成为第一个响应者,但没有成功。在这种情况下,只有创建的第一个单元格成为第一个响应者,而后续单元格被创建,但光标保留在第一个单元格中。

以下是我在cell.inboxTaskTextView.becomeFirstResponder()之前用于滚动的代码块-

DispatchQueue.main.async {
    self.tableView.reloadData()
    let indexPath = IndexPath(row: Task.tasks.count - 1, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}

编辑-

在尝试了一段时间后,这是我离解决方案最近的一次。

Task.tasks.append("")之后,我添加了以下代码,用于将视图向下滚动到底部-

if tableView.contentSize.height >= tableView.frame.size.height {
        DispatchQueue.main.async {
            self.tableView.reloadData()
            let indexPath = IndexPath(row: Task.tasks.count - 1, section: 0)
            self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
        }
}

在这种情况下,新创建的细胞成为第一响应者,但只是暂时的。键盘甚至还没有完全显示出来,它就会在一瞬间被自动关闭。只有在折叠下方创建的单元格才会发生这种情况-即,当表格视图必须向下滚动然后创建新的单元格时。

anauzrmj

anauzrmj1#

首先,试着保持简单。将断点或print("indexPath.row = \(indexPath.row)")放在您已经实现的cellForRow UITableViewDataSource方法的开头。

添加新任务,并查看是否为与新单元格对应的indexPath调用了cellForRow。

如果没有,您可能需要将TableView向上滚动至少44个点或任何需要的点,才能到达新单元格应该已经显示的区域。如果不这样做-单元格可能还没有创建,cell很可能引用表视图中的最后一个单元格(或者,如果某些逻辑没有正确实现,它也可能引用池中的单元格)。因此,在使其UITextFieldUITextView成为第一响应者之前,新细胞必须处于可见区域。

如果您知道该单元格已经可见-最好通过

let index = IndexPath(row: rowForNewCell, section: 0)
let cell = self.table.cellForRow(at: index)

最后,请致电:

cell.inboxTaskTextView.becomeFirstResponder()

相关问题