UITextField:密码实现
Posted
技术标签:
【中文标题】UITextField:密码实现【英文标题】:UITextField: Password Implementation 【发布时间】:2016-04-27 13:41:45 【问题描述】:我有一个 OTP 屏幕,我必须在 4 Diff TextFields 中输入 4 位密码的 OTP,场景是这样的:
-
每个文本字段的最大字符数限制为 1,当用户在文本字段中输入一个字符时,它应该移动到下一个文本字段。
当用户单击退格时,它应该返回到上一个文本字段以便进行更改。
我已经管理了高达 70% 的工作,但只有当用户输入所有文本字段时,退格才有效。我正在粘贴我的代码。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// This allows numeric text only, but also backspace for deletes
if (string.length > 0 && ![[NSScanner scannerWithString:string] scanInt:NULL])
return NO;
NSUInteger oldLength = [textField.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
// This 'tabs' to next field when entering digits
if (newLength == 1)
if (textField == _pin1)
[self performSelector:@selector(setNextResponder:) withObject:_pin2 afterDelay:0];
else if (textField ==_pin2)
[self performSelector:@selector(setNextResponder:) withObject:_pin3 afterDelay:0];
else if (textField == _pin3)
[self performSelector:@selector(setNextResponder:) withObject:_pin4 afterDelay:0];
//this goes to previous field as you backspace through them, so you don't have to tap into them individually
else if (oldLength > 0 && newLength == 0)
if (textField ==_pin4)
[self performSelector:@selector(setNextResponder:) withObject:_pin3 afterDelay:0];
else if (textField == _pin3)
[self performSelector:@selector(setNextResponder:) withObject:_pin2 afterDelay:0];
else if (textField == _pin2)
[self performSelector:@selector(setNextResponder:) withObject:_pin1 afterDelay:0];
return newLength <= 1;
- (void)setNextResponder:(UITextField *)nextResponder
[nextResponder becomeFirstResponder];
工作:
【问题讨论】:
密码不应该被屏蔽吗? 【参考方案1】:需要在StoryBoard
中给UITextView
添加标签。
比如 textField1 = 101,textField2 = 102,textField3 = 103,textField4 = 104
将以下代码放入您的viewcontroller
。
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField
BOOL shouldDelete = YES;
if ([textField.text length] == 0 && [textField.text isEqualToString:@""])
long tagValue = textField.tag - 1;
UITextField *txtField = (UITextField*) [self.view viewWithTag:tagValue];
[txtField becomeFirstResponder];
return shouldDelete;
以下代码为下一个UItextField
焦点。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
// This allows numeric text only, but also backspace for deletes
if (string.length > 0 && ![[NSScanner scannerWithString:string] scanInt:NULL])
return NO;
if ([textField.text length] == 0)
[self performSelector:@selector(changeTextFieldFocusToNextTextField:) withObject:textField afterDelay:0.3];
return YES;
-(void)changeTextFieldFocusToNextTextField:(UITextField*)textField
long tagValue = textField.tag + 1;
UITextField *txtField = (UITextField*) [self.view viewWithTag:tagValue];
[txtField becomeFirstResponder];
样本输出
Grab the solution demo project
【讨论】:
您能否通过在 dropbox 链接中添加项目来将整个代码发送给我?请......因为我几乎没有怀疑@nimit 因为当我在文本字段中键入文本时不会调用你的函数,所以如果你分享这个项目的整个代码,这将是一个很大的帮助。@Nimit Parekh 非常感谢@Nimit.. 等待它 @Dpak 你可以从这里找到完整的解决方案。drive.google.com/open?id=0BxVigM97JuzCM0p4eF9kV0tLeGs @Hasya 非常感谢【参考方案2】:原因是当 UITextField 为empty
时,它不会检测到backspace event
。
因此要在这种情况下检测退格事件,您必须 Subclass
UITextField 并覆盖 deleteBackward
方法。
验证以下链接了解更多详情。
Detect backspace in UITextField
编辑:添加代码。
-将所有 4 个 UITextfield 子类化为以下类。
@protocol MyTextFieldDelegate <NSObject>
@optional
- (void)textFieldDidDelete:(UITextField *)textField;
@end
@interface MyTextField : UITextField<UIKeyInput>
@property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
@end
@implementation MyTextField
- (void)deleteBackward
[super deleteBackward];
if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete:)])
[_myDelegate textFieldDidDelete:self];
@end
-将所有UITextFields的delegate设置为self,并在类中采用MyTextFieldDelegate协议
_pin1.myDelegate=self;
_pin2.myDelegate=self;
_pin3.myDelegate=self;
_pin4.myDelegate=self;
-现在实现textFieldDidDelete方法如下
- (void)textFieldDidDelete:(UITextField *)textField
if (textField ==_pin4)
[self performSelector:@selector(setNextResponder:) withObject:_pin3 afterDelay:0];
else if (textField == _pin3)
[self performSelector:@selector(setNextResponder:) withObject:_pin2 afterDelay:0];
else if (textField == _pin2)
[self performSelector:@selector(setNextResponder:) withObject:_pin1 afterDelay:0];
希望这会有所帮助。
【讨论】:
@SuryaSubenthiran 您是否尝试过在您的答案中发布的此代码。当UITextField
为空时不会检测到。
@NimitParekh。我试过。它工作正常。即使文本字段为空,也会调用 deleteBackward 方法。
@SuryaSubenthiran 这里的问题不是下一个UITextField
,而是上一个UITextField
。
@NimitParekh。如果您清楚地查看gif,您会发现问题。退格适用于最终文本字段,因为它包含文本。但其他文本字段为空。对于空文本字段,如果您按退格键,它将不会调用 shouldChangeCharactersInRange 方法。【参考方案3】:
对于 Swift 3.x
class CodeConfirmController:ViewController,UITextFieldDelegate
@IBOutlet weak var digitNum1: UITextField!
@IBOutlet weak var digitNum2: UITextField!
@IBOutlet weak var digitNum3: UITextField!
@IBOutlet weak var digitNum4: UITextField!
override func viewDidLoad()
digitNum1.delegate = self
digitNum2.delegate = self
digitNum3.delegate = self
digitNum4.delegate = self
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool
let shouldDelete: Bool = true
if textField.text?.characters.count == 0 && (textField.text == "")
let tagValue: Int = textField.tag - 1
let txtField: UITextField? = (view.viewWithTag(tagValue) as? UITextField)
txtField?.becomeFirstResponder()
return shouldDelete
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
// This allows numeric text only, but also backspace for deletes
if (string.characters.count ) > 0 && !Scanner(string: string).scanInt32(nil)
return false
if textField.text?.characters.count == 0
perform(#selector(self.changeTextFieldFocus(toNextTextField:)), with: textField, afterDelay: 0.1)
return true
func changeTextFieldFocus(toNextTextField textField: UITextField)
let tagValue: Int = textField.tag + 1
let txtField: UITextField? = (view.viewWithTag(tagValue) as? UITextField)
txtField?.becomeFirstResponder()
【讨论】:
以上是关于UITextField:密码实现的主要内容,如果未能解决你的问题,请参考以下文章
当 UITextField 被填充时,从一个类向视图控制器发送信号或触发函数
填写所有 UITextField 时,UIButton 未启用