swiftuitableviewuikituitextfieldbecomefirstresponder

UITextField can't become first responder in UITableView


Context

Basic list. When user press '+', code creates a new item with default text that user can change. UI

Problem

I want to focus the new item as soon as user press '+' so that user can type desired name. I try to achieve this with this code:

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

But becomeFirstResponder() always returns false.

How can I give focus to UITextField in my UITableviewCell after creation ?


Here is full code of UITableViewController for reference:

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)
    }
}

Solution

  • Ok I found the problem!

    I was using method self.tableView(self.tableView, cellForRowAt: indexPath) instead of self.tableView.cellForRow(at: indexPath).

    Here is what the documentation has to say: "Never call this method yourself. If you want to retrieve cells from your table, call the table view's cellForRow(at:) method instead."