ios 检测 UITextField 中的退格事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29504304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect backspace Event in UITextField
提问by Want Query
I am searching for solutions on how to capture a backspace event, most Stack Overflow answers are in Objective-C but I need on Swift language.
我正在寻找有关如何捕获退格事件的解决方案,大多数 Stack Overflow 答案都在 Objective-C 中,但我需要 Swift 语言。
First I have set delegate for the UITextField and set it to self
首先,我为 UITextField 设置了委托并将其设置为 self
self.textField.delegate = self;
Then I know to use shouldChangeCharactersInRange
delegate method to detect if a backspace was pressed is all code are in Objective-C. I need in Swift these following method as below is used.
然后我知道使用shouldChangeCharactersInRange
委托方法来检测是否按下了退格键,所有代码都在 Objective-C 中。我需要在 Swift 中使用以下方法,如下所示。
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding];
int isBackSpace = strcmp(_char, "\b");
if (isBackSpace == -8) {
// NSLog(@"Backspace was pressed");
}
return YES;
}
回答by Long Pham
Swift 4.2
斯威夫特 4.2
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let char = string.cString(using: String.Encoding.utf8) {
let isBackSpace = strcmp(char, "\b")
if (isBackSpace == -92) {
print("Backspace was pressed")
}
}
return true
}
Older Swift version
较旧的 Swift 版本
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
let isBackSpace = strcmp(char, "\b")
if (isBackSpace == -92) {
println("Backspace was pressed")
}
return true
}
回答by Ortwin Gentz
I prefer subclassing UITextField
and overriding deleteBackward()
because that is much more reliable than the hack of using shouldChangeCharactersInRange
:
我更喜欢子类化UITextField
和覆盖,deleteBackward()
因为这比使用 hack 可靠得多shouldChangeCharactersInRange
:
class MyTextField: UITextField {
override public func deleteBackward() {
if text == "" {
// do something when backspace is tapped/entered in an empty text field
}
// do something for every backspace
super.deleteBackward()
}
}
The shouldChangeCharactersInRange
hack combined with an invisible character that is placed in the text field has several disadvantages:
该shouldChangeCharactersInRange
黑客与被放置在文本字段中有不可见字符组合有几个缺点:
- with a keyboard attached, one can place the cursor before the invisible character and the backspace isn't detected anymore,
- the user can even select that invisible character (using
Shift Arrow
on a keyboard or even by tapping on the caret) and will be confused about that weird character, - the autocomplete bar offers weird choices as long as there's only this invisible character,
- Asian language keyboards that have candidate options based on the text field's text will be confused,
- the
placeholder
isn't shown anymore, - the clear button is displayed even when it shouldn't for
clearButtonMode = .whileEditing
.
- 连接键盘后,可以将光标放在不可见字符之前,不再检测到退格,
- 用户甚至可以选择那个不可见的字符(
Shift Arrow
在键盘上使用,甚至通过点击插入符号)并且会对那个奇怪的字符感到困惑, - 只要只有这个不可见的字符,自动完成栏就会提供奇怪的选择,
- 具有基于文本字段文本的候选选项的亚洲语言键盘将被混淆,
- 在
placeholder
不再被示出, - 即使不应该显示清除按钮
clearButtonMode = .whileEditing
。
Of course, overriding deleteBackward()
is a bit inconvenient due to the need of subclassing. But the better UX makes it worth the effort!
当然,deleteBackward()
由于需要子类化,覆盖有点不方便。但更好的 UX 让它值得付出努力!
And if subclassing is a no-go, e.g. when using UISearchBar
with its embedded UITextField
, method swizzling should be fine, too.
如果子类化是行不通的,例如当使用UISearchBar
其嵌入时UITextField
,方法 swizzling 也应该没问题。
回答by Insou
In Swift 3
在斯威夫特 3
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let char = string.cString(using: String.Encoding.utf8)!
let isBackSpace = strcmp(char, "\b")
if (isBackSpace == -92) {
print("Backspace was pressed")
}
return true
}
:)
:)
回答by gbk
If u need detect backspace even in empty textField (for example in case if u need auto switch back to prev textField on backSpace pressing), u can use combination of proposed methods - add invisible sign and use standard delegate method textField:shouldChangeCharactersInRange:replacementString:
like follow
如果即使在空的 textField 中您也需要检测退格(例如,如果您需要在按下退格键时自动切换回上一个 textField),您可以使用建议方法的组合 - 添加不可见符号并使用标准委托方法,textField:shouldChangeCharactersInRange:replacementString:
例如 follow
Create invisible sign
private struct Constants { static let InvisibleSign = "\u{200B}" }
Set delegate for textField
textField.delegate = self
On event
EditingChanged
check text and if needed add invisible symbol like follow:@IBAction func didChangeEditingInTextField(sender: UITextField) { if var text = sender.text { if text.characters.count == 1 && text != Constants.InvisibleSign { text = Constants.InvisibleSign.stringByAppendingString(text) sender.text = text } } }
创建隐形标志
private struct Constants { static let InvisibleSign = "\u{200B}" }
为 textField 设置委托
textField.delegate = self
在事件
EditingChanged
检查文本上,如果需要,添加不可见符号,如下所示:@IBAction func didChangeEditingInTextField(sender: UITextField) { if var text = sender.text { if text.characters.count == 1 && text != Constants.InvisibleSign { text = Constants.InvisibleSign.stringByAppendingString(text) sender.text = text } } }
Add implementation of delegate method
textField:shouldChangeCharactersInRange:replacementString:
extension UIViewController : UITextFieldDelegate { // MARK: - UITextFieldDelegate func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let char = string.cStringUsingEncoding(NSUTF8StringEncoding)! let isBackSpace = strcmp(char, "\b") if (isBackSpace == -92) { if var string = textField.text { string = string.stringByReplacingOccurrencesOfString(Constants.InvisibleSign, withString: "") if string.characters.count == 1 { //last visible character, if needed u can skip replacement and detect once even in empty text field //for example u can switch to prev textField //do stuff here } } } return true } }
添加委托方法的实现
textField:shouldChangeCharactersInRange:replacementString:
extension UIViewController : UITextFieldDelegate { // MARK: - UITextFieldDelegate func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let char = string.cStringUsingEncoding(NSUTF8StringEncoding)! let isBackSpace = strcmp(char, "\b") if (isBackSpace == -92) { if var string = textField.text { string = string.stringByReplacingOccurrencesOfString(Constants.InvisibleSign, withString: "") if string.characters.count == 1 { //last visible character, if needed u can skip replacement and detect once even in empty text field //for example u can switch to prev textField //do stuff here } } } return true } }
回答by Dmitry Kozlov
Please don't trash your code. Just put this extension somewhere in your code.
请不要丢弃您的代码。只需将此扩展名放在代码中的某个位置即可。
Swift 5.1
斯威夫特 5.1
extension String {
var isBackspace: Bool {
let char = self.cString(using: String.Encoding.utf8)!
return strcmp(char, "\b") == -92
}
}
And then just use it in your functions
然后在你的函数中使用它
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.isBackspace {
// do something
}
return true
}
回答by Augustine P A
Try this
尝试这个
public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if(string == "") {
print("Backspace pressed");
return true;
}
}
Note: You can return "true" if you want to allow backspace. Else you can return "false".
注意:如果你想允许退格,你可以返回“ true”。否则你可以返回“ false”。
回答by Roman Romanenko
I implemented this feature:
我实现了这个功能:
And in the case where the last textFiled is empty, I just want to switch to the previous textFiled. I tried all of the answers above, but no one works fine in my situation. For some reason, if I add more logic than print
in isBackSpace == -92
parentheses block this method just stopped work...
而在最后一个 textFiled 为空的情况下,我只想切换到上一个 textFiled。我尝试了上面的所有答案,但没有一个在我的情况下工作正常。出于某种原因,如果我不是增加更多的逻辑print
在isBackSpace == -92
括号阻止这种方法刚刚停止工作...
As for me the method below more elegant and works like a charm:
至于我,下面的方法更优雅,而且效果很好:
Swift
迅速
class YourTextField: UITextField {
// MARK: Life cycle
override func awakeFromNib() {
super.awakeFromNib()
}
// MARK: Methods
override func deleteBackward() {
super.deleteBackward()
print("deleteBackward")
}
}
Thanks @LombaX for the answer
感谢@LombaX 的回答
回答by Amr Angry
Swift 4
斯威夫特 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let char = string.cString(using: String.Encoding.utf8)!
let isBackSpace = strcmp(char, "\b")
if isBackSpace == -92 {
print("Backspace was pressed")
return false
}
}
回答by GreenCamper
Swift 4
斯威夫特 4
I find the comparison using strcmp
irrelevant. We don't even know how strcmp
is operating behind the hoods.In all the other answers when comparing current char and \b
results are -8
in objective-C and -92
in Swift. I wrote this answer because the above solutions did not work for me. ( Xcode Version 9.3 (9E145)
using Swift 4.1
)
我发现使用strcmp
不相关的比较。我们甚至不知道strcmp
幕后是如何操作的。在比较当前字符和\b
结果时,所有其他答案都-8
在 Objective-C 和-92
Swift 中。我写这个答案是因为上述解决方案对我不起作用。(9.3 (9E145)
使用 Swift 的Xcode 版本4.1
)
FYI :Every character that you actually type is an array of 1
or more elements in utf8 Encoding
. backSpace Character is [0]
. You can try this out.
FYI:你实际键入的每个字符是一个数组1
或多个元素utf8 Encoding
。退格字符是[0]
. 你可以试试这个。
PS :Don't forget to assign the proper delegates
to your textFields
.
PS:不要忘记delegates
为您的textFields
.
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let char = string.cString(using: String.Encoding.utf8)!
if (char.elementsEqual([0])) {
print("Backspace was pressed")
}
else {
print("WHAT DOES THE FOX SAY ?\n")
print(char)
}
return true
}
回答by Shakeel Ahmed
Swift 4
斯威夫特 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//MARK:- If Delete button click
let char = string.cString(using: String.Encoding.utf8)!
let isBackSpace = strcmp(char, "\b")
if (isBackSpace == -92) {
print("Backspace was pressed")
return true
}
}