UITextFieldをサブクラス化し、UIKeyInputプロトコルのdeleteBackwardメソッドを実装して、押されているバックスペースを検出しました。これはiOS 7では正常に機能しますが、iOS 8では機能しません。
backspaceキーを押すと、UITextFieldでdeleteBackwardが呼び出されなくなりました。
ドキュメントとリリースノートを確認しましたが、これが発生する理由については何も指摘していません。ポインタはありますか?
Githubで MBContactPicker の例を確認する必要があります。私がテストしたiOS8のBackspaceボタンを介したMBContactPickerでの連絡先の削除。そして、それは大いに働きます!例として使用できます。
MBContactPickerの作成者はnextメソッドを使用します。UITextFieldを空にする必要がある場合(または空の場合は、becomeFirstResponderを呼び出す前)、単一の空白記号をそこに保存します。そして、Backspaceボタンを押すと(フォーカスがUITextFieldのテキストの終わりに設定されたとき)、method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
働くでしょう。その中で、次のようなチェックを使用する必要があります。
NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:string];
BOOL isPressedBackspaceAfterSingleSpaceSymbol = [string isEqualToString:@""] && [resultString isEqualToString:@""] && range.location == 0 && range.length == 1;
if (isPressedBackspaceAfterSingleSpaceSymbol) {
// your actions for deleteBackward actions
}
したがって、UITextFieldに単一の空白が含まれることを常に制御する必要があります。
これはハックではありません。そのため、ユーザーは一部の動作が変更されたことに気付かないでしょう
多くの人がこれはバグだと言っていますが、この問題はGM私のアプリ用にこのコードを書き、iOS 7-8でテストしました。
次のメソッドをUITextField
サブクラスに追加します。
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField {
BOOL shouldDelete = YES;
if ([UITextField instancesRespondToSelector:_cmd]) {
BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd];
if (keyboardInputShouldDelete) {
shouldDelete = keyboardInputShouldDelete(self, _cmd, textField);
}
}
BOOL isIos8 = ([[[UIDevice currentDevice] systemVersion] intValue] == 8);
BOOL isLessThanIos8_3 = ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.3f);
if (![textField.text length] && isIos8 && isLessThanIos8_3) {
[self deleteBackward];
}
return shouldDelete;
}
このコードは、プライベートAPIの赤い線の少し前ですが、使用する際に問題はないはずです。このコードのアプリはアプリストアにあります。
少し説明するために、このメソッドのスーパー実装を呼び出して、コードが失われないようにしました。テキストがなく、iOSバージョンが8〜8.2の場合、-deleteBackward
を呼び出します。
[〜#〜] edit [〜#〜]:1/22/15
サブクラス化されたUITextField
の-deleteBackward
メソッドをサブクラス化することも役立ちます。これにより、いくつかの条件付きバグが修正されます。 1つは、カスタムキーボードを使用する場合です。メソッドの例を次に示します。
- (void)deleteBackward {
BOOL shouldDismiss = [self.text length] == 0;
[super deleteBackward];
if (shouldDismiss) {
if ([self.delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
[self.delegate textField:self shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@""];
}
}
}
[〜#〜] edit [〜#〜]:4/13/15
@ Gee.Eがコメントしたように、iOS 8.3はこの問題を修正しました。変更が反映されるようにコードが更新されました。
UITextFieldデリゲートメソッドを実装することにより、ユーザーがバックスペースを使用してテキストを削除したことを検出できます。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (range.length==1 && string.length==0)
NSLog(@"backspace tapped");
return YES;
}
Swift 2.2:
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "" {
print("Backspace has been pressed")
}
return true
}
IOS8では、一部のカスタムキーボードはWord全体を削除するため、string.lengthのみを確認してください。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (string.length==0) { //Delete any cases
if(range.length > 1){
//Delete whole Word
}
else if(range.length == 1){
//Delete single letter
}
else if(range.length == 0){
//Tap delete key when textField empty
}
}
return YES;
}
これは元の質問に明示的に答えているわけではありませんが、textField(_:shouldChangeCharactersIn:replacementString:)
のドキュメントにあるような価値はありません。
"string
:指定された範囲の置換文字列。入力中、このパラメータには通常、入力された新しい文字が1つだけ含まれますが、ユーザーがテキストを貼り付ける場合はさらに文字が含まれます。以上の文字の場合、置換文字列は空です。」
したがって、textField(_:shouldChangeCharactersIn:replacementString:)
を実装し、UITextFieldDelegate
の長さが0かどうかを確認すると、string
内のバックスペースを検出できます。
ここでの他の多くの答えは、ドキュメントを参照せずにこの同じロジックを使用しているため、ソースから適切に取得することで、より快適に使用できるようになります。
BackSpaceベースの削除を検出するためのSwift 2.0バージョン、 almasからのコード投稿を参照
//For Detecting Backspace based Deletion of Entire Word in TextField
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if (range.length == 1 && string.isEmpty){
print("Used Backspace")
}
return true
}
スイフト2:
if (string.characters.count == 0 && range.length == 1) {
return true
}
このように使用する必要がありますstring.characters.count
- (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;
}
基本的に、このメソッドは、どのボタンを押している(または押したばかりの)ボタンを検出します。この入力はNSStringとして入力されます。このNSStringをC char型に変換してから、従来のバックスペース文字(\ b)と比較します。このstrcmpが-8に等しい場合、バックスペースとして検出できます。