如何在按下NavigationBar的编辑按钮时使TableViewCell中的textField可编辑?

时间:2018-01-04 13:38:18

标签: ios swift uitableview

使用Xcode ver 9.2,Swift开发iOS应用程序。

当按下NavigationBar右上角的编辑按钮时,如何更改TableViewCell中的textField以使其可编辑? 为了防止在初始显示中编辑TextField,我使用TableViewCell.swift中的awakeFromNib()设置textField.isEnabled = false。 按下编辑按钮时,我想将其设置为true,以便我可以编辑TextField。 你能告诉我怎么样吗?

对象放置和代码(括号内)之间的关系如下。

NavigationController - TableViewController(TableViewController.swift) - TableViewCell(TableViewCell.swift) - TextField

这是代码。

TableViewController.swift

import UIKit

class TableViewController: UITableViewController, TableViewCellDelegate {

    @IBOutlet var ttableView: UITableView!

    var array:[String] = ["aaa", "bbb", "ccc", "ddd", "eee"]

    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.rightBarButtonItem = self.editButtonItem
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
    }

    // 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 array.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "inputCell", for: indexPath) as! TableViewCell
        cell.textField.text = array[indexPath.row]
        cell.delegate = self
        return cell
    }

    func textFieldDidEndEditing(cell: TableViewCell, value: String) -> () {
        let path = tableView.indexPathForRow(at: cell.convert(cell.bounds.origin, to: tableView))
        array[(path?.row)!] = value
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if (editingStyle == UITableViewCellEditingStyle.delete) {
            array.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }
    }

    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {

        let cell = tableView.cellForRow(at: sourceIndexPath) as! TableViewCell
        let moveData = cell.textField.text
        array.remove(at: sourceIndexPath.row)
        array.insert(moveData!, at: destinationIndexPath.row)
    }

}

TableViewCell.swift

import UIKit

protocol TableViewCellDelegate {
    func textFieldDidEndEditing(cell: TableViewCell, value: String) -> ()
}

class TableViewCell: UITableViewCell, UITextFieldDelegate {

    var delegate: TableViewCellDelegate! = nil

    @IBOutlet weak var textField: UITextField!

    override func awakeFromNib() {
        super.awakeFromNib()
        textField.delegate = self
        textField.returnKeyType = .done

        // To prevent the TextField from being edited in the initial display 
        textField.isEnabled = false
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        self.delegate.textFieldDidEndEditing(cell: self, value: textField.text!)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

我从第一次问题和答案中添加了以下内容。

Editing screen shot: after edit button is pressed

如果数组中有许多元素,则单元格将位于屏幕之外,但我也希望所有textField都可以编辑。

var array:[String] = ["aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrr", "sss", "ttt"]

Editing screen shot for many elements

最终解决了代码

TableViewController.swift

import UIKit

class TableViewController: UITableViewController, TableViewCellDelegate {

    @IBOutlet var ttableView: UITableView!

//    var array:[String] = ["aaa", "bbb", "ccc", "ddd", "eee"]

    var array:[String] = ["aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "rrr", "sss", "ttt"]

    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.rightBarButtonItem = self.editButtonItem
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(rightBarButtonItemTapped))
    }

    // handle tap by button...
    @objc func rightBarButtonItemTapped(_ sender: UIBarButtonItem) {
        ttableView.setEditing(!ttableView.isEditing, animated: true)
        navigationItem.rightBarButtonItem?.title = ttableView.isEditing ? "Done" : "Edit"
        navigationItem.rightBarButtonItem?.style = ttableView.isEditing ? .done : .plain
        ttableView.visibleCells.forEach { cell in
            guard let cell = cell as? TableViewCell else { return }
            cell.textField.isEnabled = ttableView.isEditing
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // 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 array.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "inputCell", for: indexPath) as! TableViewCell
        cell.textField.text = array[indexPath.row]
        cell.textField.isEnabled = tableView.isEditing
        cell.delegate = self
        return cell
    }

    func textFieldDidEndEditing(cell: TableViewCell, value: String) -> () {
        let path = tableView.indexPathForRow(at: cell.convert(cell.bounds.origin, to: tableView))
        array[(path?.row)!] = value
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if (editingStyle == UITableViewCellEditingStyle.delete) {
            array.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }
    }

    override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
        if tableView.isEditing {
            return UITableViewCellEditingStyle.delete
        } else {
            return UITableViewCellEditingStyle.none
        }
    }

    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let cell = tableView.cellForRow(at: sourceIndexPath) as! TableViewCell
        let moveData = cell.textField.text
        array.remove(at: sourceIndexPath.row)
        array.insert(moveData!, at: destinationIndexPath.row)
    }

}

TableViewCell.swift

import UIKit

protocol TableViewCellDelegate {
    func textFieldDidEndEditing(cell: TableViewCell, value: String) -> ()
}

class TableViewCell: UITableViewCell, UITextFieldDelegate {

    var delegate: TableViewCellDelegate! = nil

    @IBOutlet weak var textField: UITextField!

    override func awakeFromNib() {
        super.awakeFromNib()
        textField.delegate = self
        textField.returnKeyType = .done
        //textField.isEnabled = false
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        self.delegate.textFieldDidEndEditing(cell: self, value: textField.text!)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

2 个答案:

答案 0 :(得分:0)

首先,您应该处理导航按钮,找到textField的单元格,然后设置textField.isEnabled = true

您可以这样做:

override func viewDidLoad() {
    super.viewDidLoad()

    // in your code `self.editButtonItem` is the `UIBarButtonItem`, so make sure that it configured properly
    navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(rightBarButtonItemTapped))
}

// handle tap by button...
@objc func rightBarButtonItemTapped(_ sender: UIBarButtonItem) {
    // and set `textField.isEnabled` to all `visibleCells`
    ttableView.visibleCells.forEach { cell in
        guard let cell = cell as? TableViewCell { else return }
        cell.textField.isEnabled = true
    }

    // or set `isEnabled` to specific `textField` at index 0

    if let cell = ttableView.cellForRow(at: IndexPath(row: 0, section: 0)) {
        cell.textField.isEnabled = true
    }
}

<强> UPD。

根据您的屏幕截图:

  1. 不需要设置textField.isEnabled = false

  2. 您只需要setEditing用于tableView,并在导航栏中显示相应的按钮标题。

  3. 示例:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(rightBarButtonItemTapped))
    }
    
    @objc func rightBarButtonItemTapped(_ sender: UIBarButtonItem) {
        ttableView.setEditing(!ttableView.isEditing, animated: true)
        navigationItem.rightBarButtonItem?.title = ttableView.isEditing ? "Done" : "Edit"
        navigationItem.rightBarButtonItem?.style = ttableView.isEditing ? .done : .plain
    }
    

    最后更新

    好的,现在只有你应该做的步骤:

    1. awakeFromNib代码中删除禁用textField
    2. 的代码
    3. 在viewController的cellForRowAtIndexPath方法中写cell.textField.isEnabled = tableView.isEditing
    4. 在编辑模式下设置tableView使用我的UPD代码
    5. 要启用单元格中的所有textField,您应该使用visibleCells的原始答案(我更新了此部分,现在您不应该有任何错误)。请注意,此代码仅适用于当前可见的单元格。对于其他人来说它也有效,但set textField enabled部分进入cellForRowAtIndexPath方法,因为这些单元格将出现在屏幕上。

答案 1 :(得分:0)

您可以通过创建导航栏按钮项的操作来完成此操作,在该操作中,您只需启用textField,如下所示:

{{1}}