を検出する方法はありますか Backspace/Delete 空のUITextField
でiPhoneキーボードのキーが押されましたか?いつ知りたい Backspace UITextField
が空の場合のみ押されます。
コメントの@Alex Reynoldsからの提案に基づいて、テキストフィールドの作成中に次のコードを追加しました。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleTextFieldChanged:)
name:UITextFieldTextDidChangeNotification
object:searchTextField];
この通知は受信されます(handleTextFieldChanged
関数が呼び出されます)が、まだ Backspace 空のフィールドのキー。何か案は?
この質問については混乱があるようです。通知を受け取りたいとき Backspace キーが押されました。それでおしまい。ただし、UITextField
がすでに空の場合も解決策が機能する必要があります。
これは長いショットかもしれませんが、うまくいくかもしれません。テキストフィールドのテキストをゼロ幅のスペース文字に設定してみてください\u200B
。空のテキストフィールドでバックスペースが押されると、実際にスペースが削除されます。次に、スペースを再挿入します。
ユーザーがキャレットをスペースの左側に移動すると、機能しない場合があります。
サブクラスUITextField
:
// MyTextField.Swift
import UIKit
protocol MyTextFieldDelegate {
func textFieldDidDelete()
}
class MyTextField: UITextField {
var myDelegate: MyTextFieldDelegate?
override func deleteBackward() {
super.deleteBackward()
myDelegate?.textFieldDidDelete()
}
}
実装:
// ViewController.Swift
import UIKit
class ViewController: UIViewController, MyTextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// initialize textField
let input = MyTextField(frame: CGRect(x: 50, y: 50, width: 150, height: 40))
// set viewController as "myDelegate"
input.myDelegate = self
// add textField to view
view.addSubview(input)
// focus the text field
input.becomeFirstResponder()
}
func textFieldDidDelete() {
print("delete")
}
}
サブクラスUITextField
:
//Header
//MyTextField.h
//create delegate protocol
@protocol MyTextFieldDelegate <NSObject>
@optional
- (void)textFieldDidDelete;
@end
@interface MyTextField : UITextField<UIKeyInput>
//create "myDelegate"
@property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
@end
//Implementation
#import "MyTextField.h"
@implementation MyTextField
- (void)deleteBackward {
[super deleteBackward];
if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete)]){
[_myDelegate textFieldDidDelete];
}
}
@end
ここで、MyTextFieldDelegateをUIViewController
に追加し、UITextFields
myDelegateをself
に設定するだけです。
//View Controller Header
#import "MyTextField.h"
//add "MyTextFieldDelegate" to you view controller
@interface ViewController : UIViewController <MyTextFieldDelegate>
@end
//View Controller Implementation
- (void)viewDidLoad {
//initialize your text field
MyTextField *input =
[[MyTextField alloc] initWithFrame:CGRectMake(0, 0, 70, 30)];
//set your view controller as "myDelegate"
input.myDelegate = self;
//add your text field to the view
[self.view addSubview:input];
}
//MyTextField Delegate
- (void)textFieldDidDelete {
NSLog(@"delete");
}
更新:-[UITextField deleteBackward]
をオーバーライドする例については、 JacobCaraballoの答え を参照してください。
チェックアウト UITextInput
、具体的には UIKeyInput
には deleteBackward
デリゲートメソッド thatalwaysは、削除キーが押されると呼び出されます。単純なことをしている場合は、 SimpleTextInput およびこの iPhoneによって行われるように、UILabel
をサブクラス化し、UIKeyInput
プロトコルに準拠させることを検討してくださいUIKeyInputの例 。 注:UITextInput
およびその関連(UIKeyInput
を含む)は、iOS 3.2以降でのみ使用できます。
次のようなコード:
@interface MyTextField : UITextField
@end
@implementation MyTextField
- (void)deleteBackward
{
[super deleteBackward];
//At here, you can handle backspace key pressed event even the text field is empty
}
@end
最後に、テキストフィールドのカスタムクラスプロパティを「MyTextField」に変更することを忘れないでください
迅速な実装:
import UIKit
protocol PinTexFieldDelegate : UITextFieldDelegate {
func didPressBackspace(textField : PinTextField)
}
class PinTextField: UITextField {
override func deleteBackward() {
super.deleteBackward()
// If conforming to our extension protocol
if let pinDelegate = self.delegate as? PinTexFieldDelegate {
pinDelegate.didPressBackspace(self)
}
}
}
私はsubclass
ソリューションよりも簡単な方法を確立しました。少し変わっていても大丈夫です。
- (BOOL)textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
const char * _char = [text cStringUsingEncoding:NSUTF8StringEncoding];
int isBackSpace = strcmp(_char, "\b");
if (isBackSpace == -8) {
// is backspace
}
return YES;
}
Compareの結果が-8であるのは少し奇妙です。たぶんC Programming
。しかし、その正しい仕事;)
delegate
を試してください
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
次に、range.length == 1
これは、backspace
がヒットした場合のようです。
以下のコードを使用してください。テキストフィールドが空の場合でもキーボードの削除キーを検出するのに役立ちます。
目的C:
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }
Swift:
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
Niklas Alvaeusの回答は、同様の問題で私を助けてくれました
特定の文字セットへのエントリを制限していましたが、バックスペースを無視していました。だから私はそれをチェックしたrange.length == 1
NSString
をトリミングする前。それが本当なら、文字列を返すだけで、それをトリムしません。下記参照
- (BOOL) textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
NSCharacterSet *nonNumberSet =
[[NSCharacterSet characterSetWithCharactersInString:@"0123456789."]
invertedSet];
if (range.length == 1) {
return string;
}
else {
return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0);
}
}
はい、textFieldが空の場合、以下のメソッドを使用してバックスペースを検出します。
追加する必要がありますITextFieldDelegate
yourTextField.delegate = self (必須)
スイフト:
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
目的C:
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }
Jacob's answer に問題がある人のために、テキストフィールドのサブクラスを次のように実装しました。
#import <UIKit/UIKit.h>
@class HTTextField;
@protocol HTBackspaceDelegate <NSObject>
@optional
- (void)textFieldDidBackspace:(HTTextField*)textField;
@end
@interface HTTextField : UITextField<UIKeyInput>
@property (nonatomic, assign) id<HTBackspaceDelegate> backspaceDelegate;
@end
#import "HTTextField.h"
@implementation HTTextField
- (void)deleteBackward {
[super deleteBackward];
if ([self.backspaceDelegate respondsToSelector:@selector(textFieldDidBackspace:)]){
[self.backspaceDelegate textFieldDidBackspace:self];
}
}
- (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);
}
}
if (![textField.text length] && [[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
[self deleteBackward];
}
return shouldDelete;
}
@end
バックスペースを検出するために私が見つけた最良の使用法は、ユーザーが空のUITextField
でバックスペースを押したことを検出することです。たとえば、メールアプリに「バブル」受信者がいる場合、UITextField
でバックスペースを押すと、最後の「バブル」受信者が選択されます。
これは、ジェイコブ・カラバロの答えと同様の方法で行うことができます。しかし、ジェイコブの答えでは、バックスペースを押したときにUITextField
に1文字が残っている場合、デリゲートメッセージが受信されるまでにUITextField
はすでに空なので、backspace
最大1文字のテキストフィールド。
実際には、backspace
でUITextField
を正確にゼロ文字(空)で検出する場合は、super deleteBackward
を呼び出す前にdelegate
にメッセージを送信する必要があります。例えば:
#import "MyTextField.h"
//Text field that detects when backspace is hit with empty text
@implementation MyTextField
#pragma mark - UIKeyInput protocol
-(void)deleteBackward
{
BOOL isTextFieldEmpty = (self.text.length == 0);
if (isTextFieldEmpty) {
if ([self.delegate
respondsToSelector:@selector(textFieldDidHitBackspaceWithEmptyText:)]) {
[self.delegate textFieldDidHitBackspaceWithEmptyText:self];
}
}
[super deleteBackward];
}
@end
このようなテキストフィールドのインターフェイスは次のようになります。
@protocol MyTextFieldDelegate;
@interface MyTextField : UITextField
@property(nonatomic, weak) id<MyTextFieldDelegate> delegate;
@end
@protocol MyTextFieldDelegate <UITextFieldDelegate>
@optional
-(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
@end
IOS 6では、フィールドが空のときを含め、バックスペースが押されたときにUITextFieldでdeleteBackwardメソッドが呼び出されます。そのため、UITextFieldをサブクラス化して、独自のdeleteBackward実装を提供できます(スーパーも呼び出します)。
私はまだiOS 5をサポートしているので、Andrewの答えとこれを組み合わせる必要があります。
:)「バックスペースの検出」というタイトルの場合、UIKeyboardTypeNumberPad
を使用します。
今夜も同じ質問に答えます。それを見つけるためのコードは次のとおりです。
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
NSLog([NSString stringWithFormat:@"%d", [string length]]);
}
UIKeyboardTypeNumberPad
を使用すると、ユーザーは数値またはバックスペースのみを入力できるため、文字列の長さが0の場合、バックスペースキーである必要があります。
上記が助けになることを願っています。
テキストフィールドに何が入るのかを事前に構築したり、shouldChangeCharactersInRange
メソッドに入力された特殊文字を把握するのではなく、次のことをお勧めします。
[self performSelector:@selector(manageSearchResultsDisplay)
withObject:nil
afterDelay:0];
これにより、現在の操作が完了した直後にメソッドを呼び出すことができます。これのすばらしいところは、完了するまでに、変更された値が既にUITextField
にあるということです。その時点で、その長さを確認したり、そこに基づいて検証したりできます。
.hファイルにUIKeyInputデリゲートを追加します
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField {
if ([textField isEqual:_txtFirstDigit]) {
}else if([textField isEqual:_txtSecondDigit]) {
[_txtFirstDigit becomeFirstResponder];
}else if([textField isEqual:_txtThirdDigit]) {
[_txtSecondDigit becomeFirstResponder];
}else if([textField isEqual:_txtFourthDigit]) {
[_txtThirdDigit becomeFirstResponder];
}
return YES;
}
改善されたフォーマット
最もポピュラーな答え には、テキストフィールドが空かどうかを検出する機能がありません。
つまり、TextFieldサブクラスのdeleteBackwards()メソッドをオーバーライドしても、テキストフィールドがすでに空であったかどうかはわかりません。 (deleteBackwards()の前後の両方、textField.text!
は空の文字列です:""
)
削除する前に空をチェックすることで、ここに私の改善があります。
protocol MyTextFieldDelegate: UITextFieldDelegate {
func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool)
}
class MyTextField: UITextField {
override func deleteBackward() {
// see if text was empty
let wasEmpty = text == nil || text! == ""
// then perform normal behavior
super.deleteBackward()
// now, notify delegate (if existent)
(delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
}
}
extension MyViewController: MyTextFieldDelegate {
func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
if wasEmpty {
// do what you want here...
}
}
}
IOS 8.3ではUITextFieldのサブクラス化が機能せず、deleteBackwardが呼び出されませんでした。
ここに私が使用したソリューションがあり、すべてのiOS 8バージョンで動作し、他のiOSバージョンでも動作するはずです
for textField in textFields {
textField.text = " "
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if string == "" && textField.text == " " {
// Do stuff here
return false
}
return true
}
ユーザーがバックスペースをタップしているときにテキストフィールドに値が含まれている場合は、同様のソリューションを少し改善して実装しました。これは、バックスペースが押されたときにテキストフィールドが空の場合にのみ別のテキストフィールドにフォーカスする必要がある場合に役立ちます。
protocol MyTextFieldDelegate : UITextFieldDelegate {
func textFieldDidDelete(textField: MyTextField, hasValue: Bool)
}
override func deleteBackward() {
let currentText = self.text ?? ""
super.deleteBackward()
let hasValue = currentText.isEmpty ? false : true
if let delegate = self.delegate as? MyTextFieldDelegate {
delegate.textFieldDidDelete(textField: self, hasValue: hasValue)
}
}