Home > OS >  UITextField can't become first responder in UITableView
UITextField can't become first responder in UITableView

Time:11-17

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

CodePudding user response:

You can add a boolean in your view controller to keep track of adding item i.e isAddingItem with default value false and when you add new item simply update isAddingItem to true. In tableview cellForRowAt method check for last cell of tableview and if isAddingItem is true then selected all text of textfield and make it first responder.


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
    }

Also check if you have set textfield delegate.

CodePudding user response:

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."

  • Related