[英]Detect backspace Event in UITextField
我正在尋找有關如何捕獲退格事件的解決方案,大多數 Stack Overflow 答案都在 Objective-C 中,但我需要 Swift 語言。
首先,我為 UITextField 設置了委托並將其設置為 self
self.textField.delegate = self;
然后我知道使用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;
}
斯威夫特 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
}
較舊的 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
}
我更喜歡deleteBackward()
UITextField
並覆蓋deleteBackward()
因為這比使用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()
}
}
shouldChangeCharactersInRange
hack 結合放置在文本字段中的不可見字符有幾個缺點:
Shift Arrow
,甚至通過點擊插入符號),並且會對那個奇怪的字符感到困惑,placeholder
,clearButtonMode = .whileEditing
顯示清除按鈕。 當然,由於需要子類化,覆蓋deleteBackward()
有點不方便。 但更好的 UX 讓它值得付出努力!
如果子類化是UISearchBar
,例如,當使用UISearchBar
及其嵌入的UITextField
,方法混合也應該沒問題。
當用戶刪除一個或多個字符時,替換字符串為空。
所以回答這個:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.isEmpty {
// do something
}
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if range.length > 0 {
// We convert string to NSString instead of NSRange to Range<Int>
// because NSRange and NSString not counts emoji as one character
let replacedCharacters = (string as NSString).substring(with: range)
}
return true
}
class TextField: UITextField {
var backspaceCalled: (()->())?
override func deleteBackward() {
super.deleteBackward()
backspaceCalled?()
}
}
請不要丟棄您的代碼。 只需將此擴展名放在代碼中的某個位置即可。
extension String {
var isBackspace: Bool {
let char = self.cString(using: String.Encoding.utf8)!
return strcmp(char, "\\b") == -92
}
}
然后在你的函數中使用它
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.isBackspace {
// do something
}
return true
}
在斯威夫特 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
}
:)
嘗試這個
public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if(string == "") {
print("Backspace pressed");
return true;
}
}
注意:如果你想允許退格,你可以返回“ true ”。 否則你可以返回“ false ”。
如果您需要在空的 textField 中檢測退格(例如,如果您需要在按下退格鍵時自動切換回上一個 textField),您可以使用建議的方法組合 - 添加不可見符號並使用標准委托方法textField:shouldChangeCharactersInRange:replacementString:
喜歡關注
創建隱形標志
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 } } }
添加委托方法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 } }
我實現了這個功能:
而在最后一個 textFiled 為空的情況下,我只想切換到上一個 textFiled。 我嘗試了上面的所有答案,但沒有一個在我的情況下工作正常。 出於某種原因,如果我在isBackSpace == -92
括號中添加比print
更多的邏輯,則此方法只會停止工作...
至於我,下面的方法更優雅,而且效果很好:
迅速
class YourTextField: UITextField {
// MARK: Life cycle
override func awakeFromNib() {
super.awakeFromNib()
}
// MARK: Methods
override func deleteBackward() {
super.deleteBackward()
print("deleteBackward")
}
}
感謝@LombaX 的回答
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
}
}
我發現使用strcmp
的比較無關緊要。 我們甚至不知道strcmp
在幕后是如何運作的。在比較當前 char 和\\b
所有其他答案中,objective-C 中的結果為-8
,Swift 中的結果為-92
。 我寫這個答案是因為上述解決方案對我不起作用。 (使用 Swift 4.1
Xcode 版本9.3 (9E145)
)
僅供參考:您實際鍵入的每個字符都是utf8 Encoding
中1
或多個元素的數組。 退格字符是[0]
。 你可以試試這個。
PS:不要忘記為您的textFields
分配適當的delegates
。
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
}
斯威夫特 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
}
}
Swift 4:如果用戶按下退格按鈕,則字符串為空,因此此方法強制 textField 僅接受來自指定字符集(在本例中為 utf8 字符)和退格(string.isEmpty 情況)的字符。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.cString(using: String.Encoding.utf8) != nil {
return true
} else if string.isEmpty {
return true
} else {
return false
}
}
Swift 5:根據文本視圖委托文檔,如果 shouldChangeTextIn 方法返回的替換文本為空,則用戶按下退格按鈕。 如果范圍上限大於范圍下限(或范圍計數為 1 或更多),則應刪除文本。 如果范圍上限和下限相同(或都等於 0),則沒有要刪除的文本(長度為 0 的范圍將被替換為空)。 我測試過,即使在空文本字段上也會調用它。
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard text.isEmpty else { return true } // No backspace pressed
if (range.upperBound > range.lowerBound) {
print("Backspace pressed")
} else if (range.upperBound == range.lowerBound) {
print("Backspace pressed but no text to delete")
if (textView.text.isEmpty) || (textView.text == nil) {
print("Text view is empty")
}
}
return true
}
我來這里是為了尋找如何檢測刪除的答案。 我想知道用戶點擊后 UITextView 何時為空delete
。 在測試時,我意識到我還需要捕獲整個單詞的刪除和刪減。 這是我想出的答案。
extension SomeViewController: UITextViewDelegate {
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
let deleteTapped = text == ""
let cursorAtBeginning = range.location == 0
let deletedCharactersEqualToTextViewCount = range.length == textView.text.count
let everythingWasDeleted = deleteTapped && cursorAtBeginning && deletedCharactersEqualToTextViewCount
if everythingWasDeleted {
// Handle newly empty view from deletion
} else {
// Handle other situation
}
return true
}
}
感謝之前所有有用的答案。 我希望這可以幫助別人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.