Swift如何创建OTP验证屏幕并在多个uitextfield上向后检测删除 [英] How to create OTP verification screen and detect delete backward on multiple uitextfield is Swift
问题描述
所以我做这个otp屏幕,但是我有一些收获,
我用一堆uitextfield制作了这个otp屏幕,并给出了它的逻辑,但我只是无法删除我制作的textfield中的num
当我像我的数字的前2个一样填充文本字段时,不会删除文本字段,即使我按下ess backButton也不会起作用.....但是当我填充整个文本字段的数量(在我的情况下是六个)时,它将起作用./p>
所以我必须填写所有六个数字,并且我可以从文本字段中删除该数字,如果仅在文本字段中填写一半,它将无法正常工作.
这是我的代码:
func textField(_ textField:UITextField,shouldChangeCharacters在范围内:NSRange,replacementString字符串:String)->布尔{if((textField.text?.count)!< 1)&&(string.count> 0){如果textField == txtOTP1 {txtOTP2.becomeFirstResponder()}如果textField == txtOTP2 {txtOTP3.becomeFirstResponder()}如果textField == txtOTP3 {txtOTP4.becomeFirstResponder()}如果textField == txtOTP4 {txtOTP5.becomeFirstResponder()}如果textField == txtOTP5 {txtOTP6.becomeFirstResponder()}如果textField == txtOTP6 {txtOTP6.resignFirstResponder()}textField.text =字符串返回假}否则if(((textField.text?.count)!> = 1)&&(string.count == 0){如果textField == txtOTP2 {txtOTP1.becomeFirstResponder()}如果textField == txtOTP3 {txtOTP2.becomeFirstResponder()}如果textField == txtOTP4 {txtOTP3.becomeFirstResponder()}如果textField == txtOTP5 {txtOTP4.becomeFirstResponder()}如果textField == txtOTP6 {txtOTP5.becomeFirstResponder()}如果textField == txtOTP1 {txtOTP1.resignFirstResponder()}textField.text ="返回假}否则(textField.text?.count)!> = 1 {textField.text =字符串返回假}返回真}
那是我用来制作otp uitextField逻辑的代码……请告诉我,我知道我的逻辑有问题,谢谢.
- 我观看了在vid中制作otp屏幕的教程 https://www.youtube.com/watch?v=gZnBXh0TRO8
并且根据制造商,他说要解决此问题,我只需要将文本字段的用户交互设置为false并使第一个文本字段成为第一响应者",我认为我只是这样做了,但是我也许做错了....
我真的需要修复这个家伙,谢谢.
我更喜欢创建一个自定义文本字段,该字段将在按下deleteBackward键时通知用户,而不是固定该代码.因此,首先子类化UITextField:
导入UIKitclass SingleDigitField:UITextField {//创建一个布尔属性以保存deleteBackward信息varPressedDelete = false//根据需要自定义文本字段覆盖func willMove(toSuperview newSuperview:UIView?){keyboardType = .numberPadtextAlignment = .centerbackgroundColor = .blueisSecureTextEntry = trueisUserInteractionEnabled = false}//隐藏光标覆盖func caretRect(用于位置:UITextPosition)->CGRect {.zero}//隐藏选择覆盖func selectionRects(用于范围:UITextRange)->[UITextSelectionRect] {[]}//禁用复制粘贴覆盖func canPerformAction(_ action:选择器,withSender发件人:任何?)->布尔{false}//覆盖deleteBackward方法,将属性值设置为true并发送一个操作进行editChanged覆盖func deleteBackward(){pressDelete =真sendActions(用于:.editingChanged)}}
现在在您的ViewCOntroller中:
导入UIKit类ViewController:UIViewController {//连接文本字段出口@IBOutlet弱var firstDigitField:SingleDigitField!@IBOutlet弱var secondDigitField:SingleDigitField!@IBOutlet弱var thirdDigitField:SingleDigitField!@IBOutlet弱var fourDigitField:SingleDigitField!覆盖func viewDidLoad(){super.viewDidLoad()//为每个字段添加更改的编辑目标[firstDigitField,secondDigitField,thirdDigitField,fourthDigitField] .forEach {$ 0?.addTarget(self,action:#selector(editingChanged),for:.editingChanged)}//将firsDigitField设为第一响应者firstDigitField.isUserInteractionEnabled = truefirstDigitField.becomeFirstResponder()}//在这里,您可以控制字段中发生的每个更改所发生的情况@objc func editedChanged(__ textField:SingleDigitField){//检查是否按下了deleteBackwards键如果textField.pressedDelete {//重置其状态textField.pressedDelete = false//如果该字段的文本为空,则其内容如果textField.hasText {textField.text ="} 别的 {//否则切换该字段,请辞职第一响应者并激活前一个字段并清空其内容切换textField {情况secondDigitField,thirdDigitField,fourthDigitField:textField.resignFirstResponder()textField.isUserInteractionEnabled = false切换textField {案例secondDigitField:firstDigitField.isUserInteractionEnabled = truefirstDigitField.becomeFirstResponder()firstDigitField.text ="案例thirdDigitField:secondDigitField.isUserInteractionEnabled = truesecondDigitField.becomeFirstResponder()secondDigitField.text ="案例fourDigitField:thirdDigitField.isUserInteractionEnabled = truethirdDigitField.becomeFirstResponder()thirdDigitField.text ="默认:休息}默认值:break}}}//确保只有一个字符并且是一个数字,否则请删除其内容保护textField.text?.count == 1,textField.text?.last?.isWholeNumber == true else {textField.text ="返回}//切换textField,辞职第一个响应者并使下一个字段处于活动状态切换textField {情况firstDigitField,secondDigitField,thirdDigitField:textField.resignFirstResponder()textField.isUserInteractionEnabled = false切换textField {案例firstDigitField:secondDigitField.isUserInteractionEnabled = truesecondDigitField.becomeFirstResponder()案例secondDigitField:thirdDigitField.isUserInteractionEnabled = truethirdDigitField.becomeFirstResponder()案例thirdDigitField:fourDigitField.isUserInteractionEnabled = truefourDigitField.becomeFirstResponder()默认值:break}案例fourDigitField:fourDigitField.resignFirstResponder()默认值:break}}}
so i make this otp screen but i have some catch,
i make this otp screen with bunch of uitextfield and i make the logic of it, but i just cant delete on of the num in the textfield that i make
the textfield wont delete when i fill like the first 2 of my num, even i pressess backButton it wont work.....but it will work when i fill the whole num of textfield, in my case is six.
so i have to fill all six of the number and i can delete the number from the textfield, it wont work if only half fill in the textfield.
heres my code :
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if ((textField.text?.count)! < 1) && (string.count > 0) {
if textField == txtOTP1 {
txtOTP2.becomeFirstResponder()
}
if textField == txtOTP2 {
txtOTP3.becomeFirstResponder()
}
if textField == txtOTP3 {
txtOTP4.becomeFirstResponder()
}
if textField == txtOTP4 {
txtOTP5.becomeFirstResponder()
}
if textField == txtOTP5{
txtOTP6.becomeFirstResponder()
}
if textField == txtOTP6{
txtOTP6.resignFirstResponder()
}
textField.text = string
return false
}else if ((textField.text?.count)! >= 1) && (string.count == 0) {
if textField == txtOTP2{
txtOTP1.becomeFirstResponder()
}
if textField == txtOTP3{
txtOTP2.becomeFirstResponder()
}
if textField == txtOTP4{
txtOTP3.becomeFirstResponder()
}
if textField == txtOTP5{
txtOTP4.becomeFirstResponder()
}
if textField == txtOTP6{
txtOTP5.becomeFirstResponder()
}
if textField == txtOTP1{
txtOTP1.resignFirstResponder()
}
textField.text = ""
return false
}
else if (textField.text?.count)! >= 1 {
textField.text = string
return false
}
return true
}
thats the code i use to make the otp uitextField logic......please tell me i know theres something wrong with my logic, thanks.
- i watch a tutorial to make this otp screen in this vid https://www.youtube.com/watch?v=gZnBXh0TRO8
and according to the maker, he said that to fix this issue i just need to "set user interactions for textfield false and make first textfield first responder", i think i just did that but i maybe i did it wrong....
i really need to fix this guys, thanks.
Instead of fixing that code I prefer to create a custom text field that would inform when the deleteBackward key is pressed. So first subclass a UITextField:
import UIKit
class SingleDigitField: UITextField {
// create a boolean property to hold the deleteBackward info
var pressedDelete = false
// customize the text field as you wish
override func willMove(toSuperview newSuperview: UIView?) {
keyboardType = .numberPad
textAlignment = .center
backgroundColor = .blue
isSecureTextEntry = true
isUserInteractionEnabled = false
}
// hide cursor
override func caretRect(for position: UITextPosition) -> CGRect { .zero }
// hide selection
override func selectionRects(for range: UITextRange) -> [UITextSelectionRect] { [] }
// disable copy paste
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { false }
// override deleteBackward method, set the property value to true and send an action for editingChanged
override func deleteBackward() {
pressedDelete = true
sendActions(for: .editingChanged)
}
}
Now in your ViewCOntroller:
import UIKit
class ViewController: UIViewController {
// connect the textfields outlets
@IBOutlet weak var firstDigitField: SingleDigitField!
@IBOutlet weak var secondDigitField: SingleDigitField!
@IBOutlet weak var thirdDigitField: SingleDigitField!
@IBOutlet weak var fourthDigitField: SingleDigitField!
override func viewDidLoad() {
super.viewDidLoad()
// add a target for editing changed for each field
[firstDigitField,secondDigitField,thirdDigitField,fourthDigitField].forEach {
$0?.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
}
// make the firsDigitField the first responder
firstDigitField.isUserInteractionEnabled = true
firstDigitField.becomeFirstResponder()
}
// here you control what happens to each change that occurs to the fields
@objc func editingChanged(_ textField: SingleDigitField) {
// check if the deleteBackwards key was pressed
if textField.pressedDelete {
// reset its state
textField.pressedDelete = false
// if the field has text empty its content
if textField.hasText {
textField.text = ""
} else {
// otherwise switch the field, resign the first responder and activate the previous field and empty its contents
switch textField {
case secondDigitField, thirdDigitField, fourthDigitField:
textField.resignFirstResponder()
textField.isUserInteractionEnabled = false
switch textField {
case secondDigitField:
firstDigitField.isUserInteractionEnabled = true
firstDigitField.becomeFirstResponder()
firstDigitField.text = ""
case thirdDigitField:
secondDigitField.isUserInteractionEnabled = true
secondDigitField.becomeFirstResponder()
secondDigitField.text = ""
case fourthDigitField:
thirdDigitField.isUserInteractionEnabled = true
thirdDigitField.becomeFirstResponder()
thirdDigitField.text = ""
default:
break
}
default: break
}
}
}
// make sure there is only one character and it is a number otherwise delete its contents
guard textField.text?.count == 1, textField.text?.last?.isWholeNumber == true else {
textField.text = ""
return
}
// switch the textField, resign the first responder and make the next field active
switch textField {
case firstDigitField, secondDigitField, thirdDigitField:
textField.resignFirstResponder()
textField.isUserInteractionEnabled = false
switch textField {
case firstDigitField:
secondDigitField.isUserInteractionEnabled = true
secondDigitField.becomeFirstResponder()
case secondDigitField:
thirdDigitField.isUserInteractionEnabled = true
thirdDigitField.becomeFirstResponder()
case thirdDigitField:
fourthDigitField.isUserInteractionEnabled = true
fourthDigitField.becomeFirstResponder()
default: break
}
case fourthDigitField:
fourthDigitField.resignFirstResponder()
default: break
}
}
}
这篇关于Swift如何创建OTP验证屏幕并在多个uitextfield上向后检测删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!