Nit*_*hin 40 iphone uitextfield
我有一个奇怪的问题,当我尝试编辑它时,我的UITextField持有一个安全条目总是被清除.我在字段中添加了3个字符,转到另一个字段并返回,光标位于第4个字符位置,但是当我尝试添加另一个字符时,字段中的整个文本被新字符清除.我在笔尖中取消选中"在编辑开始时清除".那么问题是什么?如果我删除了安全入口属性,一切正常,那么,这是安全入口文本字段的属性吗?有什么方法可以防止这种行为吗?
Emp*_*ack 47
组,
textField.clearsOnBeginEditing = NO;
Run Code Online (Sandbox Code Playgroud)
注意:如果secureTextEntry = YES,则无效.看来,默认情况下,iOS会在编辑之前清除安全条目文本字段的文本,无论clearsOnBeginEditing是YES还是NO.
Eri*_*ric 47
如果您不希望字段清除,即使在secureTextEntry = YES时,请使用:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
textField.text = updatedString;
return NO;
}
Run Code Online (Sandbox Code Playgroud)
在向注册视图添加显示/隐藏密码文本功能时遇到了类似的问题.
Tho*_*eek 21
如果你正在使用Swift 3,那就给这个子类吧.
class PasswordTextField: UITextField {
override var isSecureTextEntry: Bool {
didSet {
if isFirstResponder {
_ = becomeFirstResponder()
}
}
}
override func becomeFirstResponder() -> Bool {
let success = super.becomeFirstResponder()
if isSecureTextEntry, let text = self.text {
self.text?.removeAll()
insertText(text)
}
return success
}
}
Run Code Online (Sandbox Code Playgroud)
为什么这样做?
TL; DR:如果您在切换时编辑字段isSecureTextEntry,请确保拨打电话becomeFirstResponder.
切换工作的值,isSecureTextEntry直到用户编辑文本字段 - 文本字段在放置新字符之前清除.这个暂定的结算似乎发生在becomeFirstResponder召唤期间UITextField.如果此调用与deleteBackward/ insertTexttrick 结合(如@Aleksey和@dwsolberg的答案所示),则保留输入文本,似乎取消了暂定清算.
但是,当isSecureTextEntry文本字段是第一响应者时更改的值(例如,用户键入其密码,来回切换"显示密码"按钮,然后继续键入),文本字段将照常重置.
要在此方案中保留输入文本,becomeFirstResponder只有在textfield是第一个响应者时才会触发此子类.其他答案中似乎缺少此步骤.
谢谢@Patrick Ridd的纠正!
Ahm*_*aka 16
@ Eric的答案有效,但我有两个问题.
我的最终代码
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Setting the new text.
NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
textField.text = updatedString;
//Setting the cursor at the right place
NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];
//Sending an action
[textField sendActionsForControlEvents:UIControlEventEditingChanged];
return NO;
}
Run Code Online (Sandbox Code Playgroud)
@Mars的Swift3补充:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let nsString:NSString? = textField.text as NSString?
let updatedString = nsString?.replacingCharacters(in:range, with:string);
textField.text = updatedString;
//Setting the cursor at the right place
let selectedRange = NSMakeRange(range.location + string.length, 0)
let from = textField.position(from: textField.beginningOfDocument, offset:selectedRange.location)
let to = textField.position(from: from!, offset:selectedRange.length)
textField.selectedTextRange = textField.textRange(from: from!, to: to!)
//Sending an action
textField.sendActions(for: UIControlEvents.editingChanged)
return false;
}
Run Code Online (Sandbox Code Playgroud)
Sha*_*med 12
斯威夫特 5
yourtextfield.clearsOnInsertion = false
yourtextfield.clearsOnBeginEditing = false
Run Code Online (Sandbox Code Playgroud)
注意:如果secureTextEntry = YES,这将不起作用。似乎默认情况下,iOS 在编辑之前清除安全输入文本字段的文本,无论 clearsOnBeginEditing 是 YES 还是 NO。
简单的方法使用类及其工作 100%
class PasswordTextField: UITextField {
override var isSecureTextEntry: Bool {
didSet {
if isFirstResponder {
_ = becomeFirstResponder()
//MARK:- Do something what you want
}
}
}
override func becomeFirstResponder() -> Bool {
let success = super.becomeFirstResponder()
if isSecureTextEntry, let text = self.text {
self.text?.removeAll()
insertText(text)
}
return success
}
}
Run Code Online (Sandbox Code Playgroud)
小智 7
@Thomas Verbeek的回答对我帮助很大:
class PasswordTextField: UITextField {
override var isSecureTextEntry: Bool {
didSet {
if isFirstResponder {
_ = becomeFirstResponder()
}
}
}
override func becomeFirstResponder() -> Bool {
let success = super.becomeFirstResponder()
if isSecureTextEntry, let text = self.text {
deleteBackward()
insertText(text)
}
return success
}
}
Run Code Online (Sandbox Code Playgroud)
除了我确实在我的代码中发现了一个错误.在实现他的代码之后,如果textField中有文本并点击textField框,它将只删除第一个字符,然后再次插入所有文本.基本上再次粘贴文本.
为了解决这个问题,我deleteBackward()用a 替换了self.text?.removeAll()它,它就像一个魅力.
没有托马斯的原始解决方案,我就不会那么远,所以谢谢托马斯!
iOS 12、斯威夫特 4
如果您不仅想将此解决方案用于安全文本输入,请添加 isSecureTextEntry 检查。
class PasswordTextField: UITextField {
override func becomeFirstResponder() -> Bool {
let wasFirstResponder = isFirstResponder
let success = super.becomeFirstResponder()
if !wasFirstResponder, let text = self.text {
insertText("\(text)+")
deleteBackward()
}
return success
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到了类似的问题.我在表视图中嵌入了登录(secureEntry = NO)和密码(secureEntry = YES)文本字段.我尝试过设置
textField.clearsOnBeginEditing = NO;
Run Code Online (Sandbox Code Playgroud)
在两个相关的委托方法(textFieldDidBeginEditing和textFieldShouldBeginEditing)里面,这些都没有用.从密码字段移动到登录字段后,如果我尝试删除单个字符,整个登录字段将被清除.我使用textFieldShouldChangeCharactersInRange来解决我的问题,如下所示:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (range.length == 1 && textField.text.length > 0)
{
//reset text manually
NSString *firstPart = [textField.text substringToIndex:range.location]; //current text minus one character
NSString *secondPart = [textField.text substringFromIndex:range.location + 1]; //everything after cursor
textField.text = [NSString stringWithFormat:@"%@%@", firstPart, secondPart];
//reset cursor position, in case character was not deleted from end of
UITextRange *endRange = [textField selectedTextRange];
UITextPosition *correctPosition = [textField positionFromPosition:endRange.start offset:range.location - textField.text.length];
textField.selectedTextRange = [textField textRangeFromPosition:correctPosition toPosition:correctPosition];
return NO;
}
else
{
return YES;
}
}
Run Code Online (Sandbox Code Playgroud)
当用户输入退格时,range.length == 1返回true,这是(奇怪)唯一一次我看到该字段被清除.
我已经在这里和那里尝试了所有的解决方案,最后带来了压倒一切:
- (BOOL)becomeFirstResponder
{
BOOL became = [super becomeFirstResponder];
if (became) {
NSString *originalText = [self text];
//Triggers UITextField to clear text as first input
[self deleteBackward];
//Requires setting text via 'insertText' to fire all associated events
[self setText:@""];
[self insertText:originalText];
}
return became;
}
Run Code Online (Sandbox Code Playgroud)
它会触发UITextField的清除,然后恢复原始文本.
基于 Aleksey 的解决方案,我正在使用这个子类。
class SecureNonDeleteTextField: UITextField {
override func becomeFirstResponder() -> Bool {
guard super.becomeFirstResponder() else { return false }
guard self.secureTextEntry == true else { return true }
guard let existingText = self.text else { return true }
self.deleteBackward() // triggers a delete of all text, does NOT call delegates
self.insertText(existingText) // does NOT call delegates
return true
}
}Run Code Online (Sandbox Code Playgroud)
更改范围内的替换字符对我来说不起作用,因为我有时会用它做其他事情,并且添加更多字符可能会导致错误。
这很好,因为它几乎可以完美地工作。唯一奇怪的是,当您重新点击该字段时,最后一个字符会再次显示。我实际上很喜欢它,因为它充当了一种占位符。
| 归档时间: |
|
| 查看次数: |
34498 次 |
| 最近记录: |