Swift 5.1의 경우 한 자리 수의 텍스트 필드에 대한 포괄적 인 처리기 :
- textFields의 콘센트 컬렉션이 있다고 가정합니다 (연결된 대리자 포함)
1 단계
protocol MyTextFieldDelegate: class {
func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool)
}
final class MyTextField: UITextField {
weak var myDelegate: MyTextFieldDelegate?
override func deleteBackward() {
let wasEmpty = text == nil || text == ""
// then perform normal behavior
super.deleteBackward()
// now, notify delegate (if existent)
(delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
}
}
2 단계
final class ViewController: UIViewController {
@IBOutlet private var textFields: [MyTextField]!
override func viewDidLoad() {
super.viewDidLoad()
textFields.forEach {
$0.delegate = self
$0.myDelegate = self
}
}
}
3 단계
extension ViewController: UITextFieldDelegate, MyTextFieldDelegate {
func textFieldHasChanged(with text: String, _ tag: Int, for textField: UITextField) {
textField.text = text
if let someTextField = (textFields.filter { $0.tag == tag }).first {
someTextField.becomeFirstResponder()
} else {
view.endEditing(true)
}
}
func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
// If the user was pressing backward and the value was empty, go to previous textField
textFieldHasChanged(with: "", textField.tag - 1, for: textField)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Restrict to only digits
let aSet = NSCharacterSet(charactersIn: "0123456789").inverted
let compSepByCharInSet = string.components(separatedBy: aSet)
let numberFiltered = compSepByCharInSet.joined(separator: "")
guard string == numberFiltered, let text = textField.text else { return false }
if text.count >= 1 && string.isEmpty {
// If the user is deleting the value
textFieldHasChanged(with: "", textField.tag - 1, for: textField)
} else {
textFieldHasChanged(with: string, textField.tag + 1, for: textField)
}
return false
}
}