バックスペースイベントをキャプチャする方法に関するソリューションを探しています。ほとんどのStack Overflowの回答はObjective-Cにありますが、Swift language。
最初に、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;
}
Swift 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
}
In Swift
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
}
:)
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
ハックとテキストフィールドに配置された不可視文字との組み合わせには、いくつかの欠点があります。
Shift Arrow
_を使用するか、キャレットをタップすることもできます)、その奇妙な文字について混乱します。placeholder
は表示されなくなり、clearButtonMode = .whileEditing
_を使用する必要がない場合でも、クリアボタンが表示されます。もちろん、deleteBackward()
のオーバーライドは、サブクラス化が必要なため、少し不便です。しかし、より良いUXは努力する価値があります!
そして、サブクラス化が禁止されている場合、例えば埋め込みUISearchBar
でUITextField
を使用する場合、メソッドのスウィズルも問題ないはずです。
空のtextFieldでもバックスペースを検出する必要がある場合(たとえば、BackSpaceを押すとprev 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
}
}
これを試して
public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if(string == "") {
print("Backspace pressed");
return true;
}
}
注:バックスペースを許可する場合は、「true」を返すことができます。それ以外の場合は、「false」を返すことができます。
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
です。上記の解決策がうまくいかなかったので、私はこの答えを書きました。 (Xcodeバージョン9.3 (9E145)
using Swift 4.1
)
FYI:実際に入力するすべての文字は、1
のutf8 Encoding
またはそれ以上の要素の配列です。 backSpace文字は[0]
です。これを試すことができます。
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
}
コードをゴミ箱に捨てないでください。この拡張機能をコードのどこかに配置するだけです。 (Swift 4.1)
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
}
この機能を実装しました。
最後のtextFiledが空の場合、前のtextFiledに切り替えたいだけです。上記の答えをすべて試しましたが、私の状況では誰もうまくいきません。何らかの理由で、isBackSpace == -92
括弧ブロックにprint
より多くのロジックを追加すると、このメソッドは動作を停止しました...
私に関しては、以下の方法はよりエレガントで魅力的なものです:
Swift
class YourTextField: UITextField {
// MARK: Life cycle
override func awakeFromNib() {
super.awakeFromNib()
}
// MARK: Methods
override func deleteBackward() {
super.deleteBackward()
print("deleteBackward")
}
}
answer をありがとう@LombaX
スイフト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:ユーザーがバックスペースボタンを押すと、文字列が空になるため、このアプローチでは、指定された文字セット(この場合は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
}
}