在开发项目中,经常会遇到多输入框页面,如果输入框样式一致或者差异较小,就可以采用tableView
来实现。但是在tableView
中重用textField
会产生两个问题:一个是键盘弹出后textField
怎样保持在键盘上方,另一个是textField
滑动后会丢失输入数据或者输入数据错乱。其实还有一个附加问题:在使用tableView
的页面如何收起键盘?
问题1:键盘弹起后,textField
怎样才能保持在键盘上方呢,一般的方式是通过监听键盘弹出和收起的通知来改变tableView
的contentOffset
,一个更简单的方式是:
1 2 3 4 5 6 7 8 9 10 11 12
| table = UITableView(frame: view.bounds, style: .plain)
let tableController = UITableViewController(style: .plain) self.addChild(tableController) table = tableController.tableView
table.register(UINib.init(nibName: "MyTextFieldCell", bundle: nil), forCellReuseIdentifier: "\(MyTextFieldCell.self)") table.delegate = self table.dataSource = self table.rowHeight = 60 table.tableFooterView = UIView() view.addSubview(table)
|
这样做是因为UITableViewController
已经为我们做好了键盘弹出收起时cell位置的变化处理。
问题2:textField
滑动后会丢失输入数据或者输入数据错乱
要解决cell重用后输入数据错乱问题,我们需要对数据进行合理的保存。在cell中实现UITextFieldDelegate的代理方法,在textFieldDidEndEditing
方法中调用cell的闭包saveInput(textField.text)
,将TextField的text内容传出去,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var saveInput:((String?)->())?
extension MyTextFieldCell:UITextFieldDelegate{ func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { if let callback = clickTextFieldBlock { callback(textField.frame) } return true } func textFieldDidEndEditing(_ textField: UITextField) { if let save = saveInput { save(textField.text) } } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } }
|
在controller中,使用infoModel变量来保存各输入框的输入内容,在cellForRow时实现cell的闭包saveInput保存数据到InfoModel,并从中取出数据给TextField展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var infoModel:[IndexPath:String] = [:]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "\(MyTextFieldCell.self)", for: indexPath) as! MyTextFieldCell cell.selectionStyle = .none cell.saveInput = { [weak self] (info) in self?.infoModel[indexPath] = info } cell.textField.text = self.infoModel[indexPath] return cell }
|
最后,在一般的viewController中,要结束输入收起键盘,调用view.endEditing(true)即可,在tableView中由于tableView响应了touchBegan的手势,所以view.endEditing(true)没有作用,这时候就需要在TextField的代理方法上来处理了,在用户点击return的时候使TextField失去第一响应即可:
1 2 3 4
| func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true }
|