是否有办法检测何时在UITextField
上的iPhone键盘上按下Backspace / Delete键是空的?我想知道只有当UITextField
为空时才按下Backspace。
根据@Alex Reynolds在评论中提出的建议,我在创建文本字段时添加了以下代码:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleTextFieldChanged:)
name:UITextFieldTextDidChangeNotification
object:searchTextField];
收到此通知(调用handleTextFieldChanged
函数),但是当我在空字段中按退格键时仍然不会。有任何想法吗?
这个问题似乎有些混乱。我想在按下退格键时收到通知。而已。但是当UITextField
已经空了时,解决方案也必须有效。
这可能是一个长镜头,但它可以工作。尝试将文本字段的文本设置为零宽度空格字符\u200B
。当在显示为空的文本字段上按下退格键时,它实际上会删除您的空间。然后你可以重新插入空间。
如果用户设法将插入符号移动到空格的左侧,则可能无法工作。
是的,当textField为空时,使用下面的方法来检测退格。
需要添加UITextFieldDelegate
yourTextField.delegate = self(必须)
迅速:
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
目标C:
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }
对于那些有关Jacob's answer问题的人,我实现了我的textfield子类如下,它的效果很好!
#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
中点击退格时,它会选择最后一个“冒泡”收件人。
这可以通过与Jacob Caraballo的答案类似的方式完成。但是在雅各布的回答中,如果UITextField
在你退格时有一个字符,那么在收到委托消息时,UITextField
已经是空的,所以你在一个文本字段中有效地检测到backspace
,最多只有一个字符。
实际上,如果你想在backspace
上检测到UITextField
,其中只有零个字符(空),那么你应该在调用delegate
之前将消息发送到super deleteBackward
。例如:
#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实现(也可以调用super)。
我仍然支持iOS 5,所以我需要安德鲁的回答和这个的结合。
:)只为标题“检测退格”,我使用UIKeyboardTypeNumberPad
。
我今晚也遇到了同样的问题,以下是我的代码来找出它:
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
NSLog([NSString stringWithFormat:@"%d", [string length]]);
}
因为使用UIKeyboardTypeNumberPad
,用户只能输入Number或backspace,所以当string的长度为0时,它必须是退格键。
希望以上会有所帮助。
我建议您不要试图预先构建文本字段中的Will BEtent或找出在shouldChangeCharactersInRange
方法中输入的特殊字符,我建议您执行以下操作:
[self performSelector:@selector(manageSearchResultsDisplay)
withObject:nil
afterDelay:0];
这允许您在当前操作完成后直接调用方法。这有什么好处,到它完成时,修改后的值已经在UITextField
中了。此时,您可以根据其中的内容检查其长度和/或进行验证。
子类化UITextField在iOS 8.3上对我不起作用,从未调用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
}
在.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;
}
改进格式
我已经实现了类似的解决方案,并进行了一些小的改进,告诉我如果文本字段在用户点击退格时有任何价值。这对我的情况非常有用,因为如果按下退格键时文本字段为空,我应该只关注另一个文本字段。
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)
}
}
The most poplar answer缺少一件事 - 能够检测文本字段是否为空。
也就是说,当您覆盖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...
}
}
}
子类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");
}
要保持简单,这是您需要检查的唯一条件
if (range.length==1)
+ (BOOL)detectBackspaceOnly:(NSString *)string
{
for(int i=0 ; i<string.length ; i++){
unichar caract = [string characterAtIndex:i];
if(caract != ' ' && caract != '\n')
return NO;
}
return YES;
}
像这样的东西:
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
if (![text hash] && ![textField.text length])
[self backspaceInEmptyTextField];
}
当然哈希是一个字符串。
使用TextField Delegate方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
在上面的方法中添加以下代码以检测删除事件
if(textField == YourTextField)
{
if ([string length] == 0 && range.length > 0)
{
// Your Code after deletion of character
}
}
在UITextViewDelegate
:
- (BOOL) textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
if(text isEqualToString:@"");
{
NSLog(@"press backspace.");
}
}
它适用于我。
更新中文简体拼音和中文手写输入:
- (BOOL) textView:(UITextView *)textView
shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
if (range.length > 0 && [text isEqualToString:@""]) {
NSLog(@"press Backspace.");
}
return YES;
}
根据文件说:
“如果用户按下deleteKey
,则范围的长度为1,空字符串对象将替换该单个字符。”
更新:请参阅JacobCaraballo's answer以获取覆盖-[UITextField deleteBackward]
的示例。
查看UITextInput
,特别是UIKeyInput
有一个deleteBackward
delegate method,当按下删除键时总是被调用。如果你正在做一些简单的事情,那么你可以考虑将UILabel
子类化并使其符合UIKeyInput
协议,正如SimpleTextInput和这个iPhone UIKeyInput Example所做的那样。注意: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”
Swift实现:
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;
}
比较结果有点奇怪-8。也许我在C Programming
的某些方面会出错。但它的正确工作;)
试试delegate
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
然后检查当range.length == 1
被击中时backspace
似乎是这种情况。
请使用下面的代码,即使textfield为空,它也可以帮助您检测键盘删除键。
目标C:
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }
斯威夫特:
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);
}
}