如何在原型单元格中同时更改 textField.text?
How to simultaneously change textField.text in a prototype cell?
我有一个 UITableViewController 和一个带有 UITextField 的原型单元格。当我在其中一个单元格中更改 textField.text 时,我希望它在我的 tableView 现在拥有的所有其他单元格中进行更改(例如,将数字乘以 2 并设置为其他单元格的 textField.text 输出)。
这是我要实现的行为:CLICK
我应该触发某个 textField 委托方法还是应该以其他方式制作?
我现在的代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.numberTextField.delegate = self
}
//Delegate methods
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.text = ""
textField.textColor = UIColor.systemBlue
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
textField.text = "0"
textField.textColor = UIColor.black
}
在您的 textFieldDidBeginEditing
和 textFieldDidChangeSelection
委托中,调用 tableView.reloadData()
高级别:
- 您需要有一个模型来存储正在更新的数据
- 您需要观察使用
UITextFieldDelegate
输入的文本
- 输入文本时,使用新计算更新活动单元格以外的所有行
最有趣的作品在textFieldDidChangeSelection
和cellForRowAt indexPath
这是我如何做这样的事情的例子:
1.设置一些自定义类型
// Your model to store data in text fields
// Maybe for you, you will store currencies
// and base currency to multiply against
// I am just storing a random number for example
struct FinanceModel
{
var number: Int?
}
// Custom UITextField which will store info
// about cell index path as we need to identify
// it when editing
class MappedTextField: UITextField
{
var indexPath: IndexPath!
}
2。 UITableView Cell示例,有自己的可以忽略
fileprivate class CustomCell: UITableViewCell
{
// Use custom text field
var textField: MappedTextField!
static let tableViewCellIdentifier = "cell"
override init(style: UITableViewCell.CellStyle,
reuseIdentifier: String?)
{
super.init(style: style,
reuseIdentifier: reuseIdentifier)
configureTextField()
}
required init?(coder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
// Configure text field and auto layout
private func configureTextField()
{
textField = MappedTextField()
textField.keyboardType = .numberPad
textField.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(textField)
textField.layer.borderWidth = 2.0
textField.layer.borderColor = UIColor.blue.cgColor
textField.layer.cornerRadius = 5.0
// auto-layout
textField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,
constant: 20).isActive = true
textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,
constant: -20).isActive = true
textField.topAnchor.constraint(equalTo: contentView.topAnchor,
constant: 20).isActive = true
textField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,
constant: -20).isActive = true
}
}
3。在视图控制器中设置 - 如果已经设置可以跳过,这里只是为了完整性
class InputViewController: UIViewController
{
let tableView = UITableView()
// Initialize your mode
var financeModel = FinanceModel()
// This will store current editing cell which is active
var activeTextFieldIndexPath: IndexPath?
override func viewDidLoad()
{
super.viewDidLoad()
// This is just view set up for me,
// You can ignore this
title = "TableView Input"
navigationController?.navigationBar.tintColor = .white
view.backgroundColor = .white
configureTableView()
}
// Configure TableView and layout
private func configureTableView()
{
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(CustomCell.self,
forCellReuseIdentifier: CustomCell.tableViewCellIdentifier)
tableView.dataSource = self
tableView.delegate = self
// remove additional rows
tableView.tableFooterView = UIView()
view.addSubview(tableView)
// Auto layout
tableView.leadingAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
tableView.topAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.trailingAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
tableView.bottomAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
4。表视图数据源
extension InputViewController: UITableViewDataSource
{
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
// Random number for me
return 10
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell =
tableView.dequeueReusableCell(withIdentifier:
CustomCell.tableViewCellIdentifier)
as! CustomCell
// Set index path of custom text field
cell.textField.indexPath = indexPath
// Set view controller to respond to text field events
cell.textField.delegate = self
// Check if any cell is currently active
// && if we are current cell is NOT the active one
// We want to leave active cell untouched
if let activeTextFieldIndexPath = activeTextFieldIndexPath,
activeTextFieldIndexPath.row != indexPath.row
{
updateCell(cell, atIndexPath: indexPath)
}
else
{
// no active cell, just set the text
updateCell(cell, atIndexPath: indexPath)
}
return cell
}
private func updateCell(_ cell: CustomCell,
atIndexPath indexPath: IndexPath)
{
// Retrieve number currently stored in model
if let number = financeModel.number
{
// Set text of number in model * row number
// Do any calculation you like, this is just an
// example
cell.textField.text =
"\(number) x \(indexPath.row) = \(number * indexPath.row)"
}
else
{
// If no valid number, set blank
cell.textField.text = ""
}
}
}
5.文本字段代表
extension InputViewController: UITextFieldDelegate
{
// Respond to new text in the text field
func textFieldDidChangeSelection(_ textField: UITextField)
{
// 1. Convert generic UITextField to MappedTextField
// 2. && Retrieve index path from custom MappedTextField
// 3. && Retrieve text from the text field
// 4. && Check if text is valid number
if let textField = textField as? MappedTextField,
let indexPath = textField.indexPath,
let text = textField.text,
let number = Int(text)
{
// Assign local variable with index path we are editing
activeTextFieldIndexPath = indexPath
// Update number in the financial model
financeModel.number = number
// We only want to update data in visible rows so
// get all the index paths of visible rows
let visibleRows = self.tableView.indexPathsForVisibleRows ?? []
// We want to update all rows EXCEPT active row
// so do a filter for this
let allRowsWithoutActive = (visibleRows).filter
{
// Remove the active index path from the
// visible index paths
[=14=].section != indexPath.section ||
[=14=].row != indexPath.row
}
// Reload the visible rows EXCEPT active
self.tableView.reloadRows(at: allRowsWithoutActive,
with: .automatic)
}
}
// This is just to make current text field
// empty when editing, you can ignore
func textFieldDidBeginEditing(_ textField: UITextField)
{
textField.text = ""
}
// Reset when text field is no longer being edited
func textFieldDidEndEditing(_ textField: UITextField)
{
activeTextFieldIndexPath = nil
tableView.reloadData()
}
}
6.表视图委托
extension InputViewController: UITableViewDelegate
{
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
// End editing when scrolling table view
// This is for me, you can have another way
view.endEditing(true)
}
func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat
{
// Return a random height
return 80
}
}
最终结果是这样的:
希望这足以让您踏上前进的道路。
我有一个 UITableViewController 和一个带有 UITextField 的原型单元格。当我在其中一个单元格中更改 textField.text 时,我希望它在我的 tableView 现在拥有的所有其他单元格中进行更改(例如,将数字乘以 2 并设置为其他单元格的 textField.text 输出)。
这是我要实现的行为:CLICK
我应该触发某个 textField 委托方法还是应该以其他方式制作?
我现在的代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.numberTextField.delegate = self
}
//Delegate methods
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.text = ""
textField.textColor = UIColor.systemBlue
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
textField.text = "0"
textField.textColor = UIColor.black
}
在您的 textFieldDidBeginEditing
和 textFieldDidChangeSelection
委托中,调用 tableView.reloadData()
高级别:
- 您需要有一个模型来存储正在更新的数据
- 您需要观察使用
UITextFieldDelegate
输入的文本
- 输入文本时,使用新计算更新活动单元格以外的所有行
最有趣的作品在textFieldDidChangeSelection
和cellForRowAt indexPath
这是我如何做这样的事情的例子:
1.设置一些自定义类型
// Your model to store data in text fields
// Maybe for you, you will store currencies
// and base currency to multiply against
// I am just storing a random number for example
struct FinanceModel
{
var number: Int?
}
// Custom UITextField which will store info
// about cell index path as we need to identify
// it when editing
class MappedTextField: UITextField
{
var indexPath: IndexPath!
}
2。 UITableView Cell示例,有自己的可以忽略
fileprivate class CustomCell: UITableViewCell
{
// Use custom text field
var textField: MappedTextField!
static let tableViewCellIdentifier = "cell"
override init(style: UITableViewCell.CellStyle,
reuseIdentifier: String?)
{
super.init(style: style,
reuseIdentifier: reuseIdentifier)
configureTextField()
}
required init?(coder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
// Configure text field and auto layout
private func configureTextField()
{
textField = MappedTextField()
textField.keyboardType = .numberPad
textField.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(textField)
textField.layer.borderWidth = 2.0
textField.layer.borderColor = UIColor.blue.cgColor
textField.layer.cornerRadius = 5.0
// auto-layout
textField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,
constant: 20).isActive = true
textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,
constant: -20).isActive = true
textField.topAnchor.constraint(equalTo: contentView.topAnchor,
constant: 20).isActive = true
textField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,
constant: -20).isActive = true
}
}
3。在视图控制器中设置 - 如果已经设置可以跳过,这里只是为了完整性
class InputViewController: UIViewController
{
let tableView = UITableView()
// Initialize your mode
var financeModel = FinanceModel()
// This will store current editing cell which is active
var activeTextFieldIndexPath: IndexPath?
override func viewDidLoad()
{
super.viewDidLoad()
// This is just view set up for me,
// You can ignore this
title = "TableView Input"
navigationController?.navigationBar.tintColor = .white
view.backgroundColor = .white
configureTableView()
}
// Configure TableView and layout
private func configureTableView()
{
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(CustomCell.self,
forCellReuseIdentifier: CustomCell.tableViewCellIdentifier)
tableView.dataSource = self
tableView.delegate = self
// remove additional rows
tableView.tableFooterView = UIView()
view.addSubview(tableView)
// Auto layout
tableView.leadingAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
tableView.topAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.trailingAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
tableView.bottomAnchor
.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
4。表视图数据源
extension InputViewController: UITableViewDataSource
{
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
// Random number for me
return 10
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell =
tableView.dequeueReusableCell(withIdentifier:
CustomCell.tableViewCellIdentifier)
as! CustomCell
// Set index path of custom text field
cell.textField.indexPath = indexPath
// Set view controller to respond to text field events
cell.textField.delegate = self
// Check if any cell is currently active
// && if we are current cell is NOT the active one
// We want to leave active cell untouched
if let activeTextFieldIndexPath = activeTextFieldIndexPath,
activeTextFieldIndexPath.row != indexPath.row
{
updateCell(cell, atIndexPath: indexPath)
}
else
{
// no active cell, just set the text
updateCell(cell, atIndexPath: indexPath)
}
return cell
}
private func updateCell(_ cell: CustomCell,
atIndexPath indexPath: IndexPath)
{
// Retrieve number currently stored in model
if let number = financeModel.number
{
// Set text of number in model * row number
// Do any calculation you like, this is just an
// example
cell.textField.text =
"\(number) x \(indexPath.row) = \(number * indexPath.row)"
}
else
{
// If no valid number, set blank
cell.textField.text = ""
}
}
}
5.文本字段代表
extension InputViewController: UITextFieldDelegate
{
// Respond to new text in the text field
func textFieldDidChangeSelection(_ textField: UITextField)
{
// 1. Convert generic UITextField to MappedTextField
// 2. && Retrieve index path from custom MappedTextField
// 3. && Retrieve text from the text field
// 4. && Check if text is valid number
if let textField = textField as? MappedTextField,
let indexPath = textField.indexPath,
let text = textField.text,
let number = Int(text)
{
// Assign local variable with index path we are editing
activeTextFieldIndexPath = indexPath
// Update number in the financial model
financeModel.number = number
// We only want to update data in visible rows so
// get all the index paths of visible rows
let visibleRows = self.tableView.indexPathsForVisibleRows ?? []
// We want to update all rows EXCEPT active row
// so do a filter for this
let allRowsWithoutActive = (visibleRows).filter
{
// Remove the active index path from the
// visible index paths
[=14=].section != indexPath.section ||
[=14=].row != indexPath.row
}
// Reload the visible rows EXCEPT active
self.tableView.reloadRows(at: allRowsWithoutActive,
with: .automatic)
}
}
// This is just to make current text field
// empty when editing, you can ignore
func textFieldDidBeginEditing(_ textField: UITextField)
{
textField.text = ""
}
// Reset when text field is no longer being edited
func textFieldDidEndEditing(_ textField: UITextField)
{
activeTextFieldIndexPath = nil
tableView.reloadData()
}
}
6.表视图委托
extension InputViewController: UITableViewDelegate
{
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
// End editing when scrolling table view
// This is for me, you can have another way
view.endEditing(true)
}
func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat
{
// Return a random height
return 80
}
}
最终结果是这样的:
希望这足以让您踏上前进的道路。