I want to add a tap gesture to every cell in a UITableView
that edits the content in it. The two ways to add a gesture are in code or through storyboard. I tried bo
The easiest way to do this is to add the gesture in a custom UITableViewCell
. An easier alternative to setting up a custom delegate pattern is to inform the view controller of the edits would be to use a handler in the form of a closure that the view controller can provide and which is called when user editing is finished. I'm assuming a textField is used to allow cell editing.
class CustomTableViewCell: UITableViewCell {
func activateTitleEditing() {
textField.isEnabled = true
textField.becomeFirstResponder()
}
// This will hold the handler closure which the view controller provides
var resignationHandler: (() -> Void)?
@objc private func tap(_ recognizer: UITapGestureRecognizer) {
guard recognizer.state == .ended else { return }
activateTitleEditing()
}
@IBOutlet weak var textField: UITextField! { didSet {
textField.delegate = self
let tap = UITapGestureRecognizer(target: self, action: #selector(tap(_:)))
addGestureRecognizer(tap)
textField.isEnabled = false
}}
}
extension CustomTableViewCell: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
resignationHandler?()
}
}
And within your custom UITableViewController
, pass in the handler to be able to make changes to your model. Don't forget to account for possible memory cycles in the closure.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// initialize and return table view cell
let cell = tableView.dequeueReusableCell(withIdentifier: K.documentCellIdentifier, for: indexPath)
assert(cell is CustomTableViewCell, "Document cell dequeuing error")
let customCell = cell as! DocumentTableViewCell
customCell.textField.text = documentModel.documents[indexPath.row]
customCell.resignationHandler = { [weak self, unowned customCell] in
guard let self = self else { return }
if let newTitle = customCell.textField.text {
self.cellModel.cells[indexPath.row] = newTitle
}
}
return customCell
}