UITextField 不能成为 UITableView 中的第一响应者

Posted

技术标签:

【中文标题】UITextField 不能成为 UITableView 中的第一响应者【英文标题】:UITextField can't become first responder in UITableView 【发布时间】:2021-11-16 11:09:58 【问题描述】:

上下文

基本列表。当用户按下“+”时,代码会创建一个带有用户可以更改的默认文本的新项目。

问题

我想在用户按下“+”后立即关注新项目,以便用户可以输入所需的名称。我尝试用这段代码来实现这一点:

func focus() 
        title.becomeFirstResponder()
        title.selectAll(nil)
    

但是becomeFirstResponder() 总是返回false

创建后如何在UITableviewCell 中将焦点放在UITextField 上?


这里是UITableViewController的完整代码供参考:

import UIKit

class ViewController: UITableViewController
    var model: [String] = ["Existing item"]
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return model.count
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "ItemUI", for: indexPath) as! ItemUI
        cell.update(with: model[indexPath.item])
        return cell
    
    
    @IBAction func createItem(_ sender: UIBarButtonItem) 
        let indexPath = IndexPath(item: model.count, section: 0)
        model.append("new item")
        tableView.reloadData()
        tableView.scrollToRow(at: indexPath, at: .top, animated: true)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) 
            let cell = self.tableView(self.tableView, cellForRowAt: indexPath) as! ItemUI
            cell.focus()
        
    


class ItemUI: UITableViewCell
    @IBOutlet var title: UITextField!
    
    func update(with: String) 
        title.text = with
    
    
    func focus() 
        title.becomeFirstResponder()
        title.selectAll(nil)
    

【问题讨论】:

【参考方案1】:

您可以在视图控制器中添加一个布尔值来跟踪添加项目,即默认值为 false 的 isAddingItem,当您添加新项目时,只需将 isAddingItem 更新为 true。在 tableview cellForRowAt 方法中检查 tableview 的最后一个单元格,如果 isAddingItem 为真,则选择文本字段的所有文本并使其成为第一响应者。


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "ItemUI", for: indexPath) as! ItemUI
        cell.update(with: model[indexPath.item])

        if isAddingItem && indexPath.item == model.count 
            // make your textfield first here and select text here
        

        return cell
    

还要检查您是否设置了文本字段委托。

【讨论】:

是一个很好的答案,您可能需要添加一个条件来检查最后一个元素是否仍然具有默认文本值,如果没有,则将其置于焦点之外。 感谢 Azhar 的回答,但我找到了真正的问题,请检查我的回答【参考方案2】:

好的,我找到了问题!

我使用的是 self.tableView(self.tableView, cellForRowAt: indexPath) 方法,而不是 self.tableView.cellForRow(at: indexPath)

这是documentation 不得不说的: “永远不要自己调用这个方法。如果你想从表格中检索单元格,请调用表格视图的cellForRow(at:) 方法。”

【讨论】:

以上是关于UITextField 不能成为 UITableView 中的第一响应者的主要内容,如果未能解决你的问题,请参考以下文章

inputAccessoryView 中的 UITextField 不会成为FirstResponder

成为FirstResponder 和多个 UITextField 焦点

如何使键盘 UITextField 中的数字视图成为默认值?

当 UITextField 成为FirstResponder 时得到通知

UITableView 单元格中的 UITextField 以编程方式成为FirstResponder

UIColletionViewCell 内的 UITextField 成为FirstResponder