如图所示,需要实现连续输入和删除的textfield
代码如下:
首先定义一个宏来实现过滤非法字符串,让输入的字符都是我定义的里面的字符。
#define kInputNumbers @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\n"
下面是定义的4个textfield
@property
(
retain
,
nonatomic
)
IBOutlet
JDTextField
*textField1;
@property ( retain , nonatomic ) IBOutlet JDTextField *textField2;
@property ( retain , nonatomic ) IBOutlet JDTextField *textField3;
@property ( retain , nonatomic ) IBOutlet JDTextField *textField2;
@property ( retain , nonatomic ) IBOutlet JDTextField *textField3;
@property
(
retain
,
nonatomic
)
IBOutlet
JDTextField
*textField4;
因为并没有直接可以调用的方法,所以要自己加上观察
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(textFieldTextDidChange:)
name
:
UITextFieldTextDidChangeNotification
object
:
nil
];
/**
* 为了统一界面,在第一个 field 之前加上 @“ ”
*
* @param textField
*/
- ( void ) textFieldDidBeginEditing:( UITextField *)textField{
if (textField == _textField1 && ! _isDelete ) {
textField. text = @" " ;
}
}
/**
* 对应的 field 改变之前调用这个方法,在这里面来控制从前面格子往后跳转
*
* @param textField textField
* @param range 传入的是改变之前光标所在的位置和长度,如果是删除的话是改变后光标的位置,长度为 -1
* @param string 改变的字符
*
* @return YES 的时候确认改变, NO 的时候抛弃改变(可以用来过滤字符)
*/
- ( BOOL )textField:( UITextField *)textField shouldChangeCharactersInRange:( NSRange )range replacementString:( NSString *)string{
// 过滤非法字符
NSCharacterSet *cs = [[ NSCharacterSet characterSetWithCharactersInString : kInputNumbers ] invertedSet ];
NSString *filtered = [[string componentsSeparatedByCharactersInSet :cs] componentsJoinedByString : @"" ];
BOOL basicTest = [string isEqualToString :filtered];
if (!basicTest) {
return NO ;
}
// 确定是否是删除键
_isDelete = string. length <= 0 ? YES : NO ;
if (textField == _textField1 ) {
// 这个方法确保手动点击某个 textfield 时可以实现跳到下一个
if (range. location == 5 ) {
[textField resignFirstResponder ];
_textField2 . enabled = YES ;
[ _textField2 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
if (range. location == 0 && _isDelete )
{
return NO ;
}
}
else if (textField == _textField2 ) {
if (range. location == 5 ) {
[textField resignFirstResponder ];
_textField3 . enabled = YES ;
[ _textField3 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
if (range. location == 0 && _isDelete ){
[textField resignFirstResponder ];
_textField1 . enabled = YES ;
[ _textField1 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
}
else if (textField == _textField3 ) {
if (range. location == 5 ) {
[textField resignFirstResponder ];
_textField4 . enabled = YES ;
[ _textField4 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
if (range. location == 0 && _isDelete ){
[textField resignFirstResponder ];
_textField2 . enabled = YES ;
[ _textField2 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
}
else {
if (range. location == 0 && _isDelete ){
[textField resignFirstResponder ];
_textField3 . enabled = YES ;
[ _textField3 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
return range. location <= 4 ;
}
return YES ;
}
/**
* 观察 textfield 改变之后的属性时调用这个方法,在这个方法里面控制往前面的格子里跳转(因为光标在第一个的时候没有回调方法,所以要在每个之前加上 @“ ” )
*
* @param notification 传入观察的对象
*/
- ( void )textFieldTextDidChange:( NSNotification *)notification
{
self . moneyLabel . hidden = YES ;
self . checkLeftBtn . enabled = NO ;
self . saveAndUseBtn . enabled = NO ;
UITextField *textField = ( UITextField *)[notification object ];
if (! _isDelete ) {
if (textField == _textField1 ) {
if (textField. text . length >= 5 ) {
_textField2 . enabled = YES ;
[textField resignFirstResponder ];
[ _textField2 becomeFirstResponder ];
_textField2 . text = @" " ;
textField. enabled = NO ;
}
} else if (textField == _textField2 ){
if (textField. text . length >= 5 ) {
_textField3 . enabled = YES ;
[textField resignFirstResponder ];
[ _textField3 becomeFirstResponder ];
_textField3 . text = @" " ;
textField. enabled = NO ;
}
} else if (textField == _textField3 ){
if (textField. text . length >= 5 ) {
_textField4 . enabled = YES ;
[textField resignFirstResponder ];
[ _textField4 becomeFirstResponder ];
_textField4 . text = @" " ;
textField. enabled = NO ;
}
}
}
if ( _textField1 . text . length + _textField2 . text . length + _textField3 . text . length + _textField4 . text . length >= 20 ) {
self . checkLeftBtn . enabled = YES ;
self . saveAndUseBtn . enabled = YES ;
}
* 为了统一界面,在第一个 field 之前加上 @“ ”
*
* @param textField
*/
- ( void ) textFieldDidBeginEditing:( UITextField *)textField{
if (textField == _textField1 && ! _isDelete ) {
textField. text = @" " ;
}
}
/**
* 对应的 field 改变之前调用这个方法,在这里面来控制从前面格子往后跳转
*
* @param textField textField
* @param range 传入的是改变之前光标所在的位置和长度,如果是删除的话是改变后光标的位置,长度为 -1
* @param string 改变的字符
*
* @return YES 的时候确认改变, NO 的时候抛弃改变(可以用来过滤字符)
*/
- ( BOOL )textField:( UITextField *)textField shouldChangeCharactersInRange:( NSRange )range replacementString:( NSString *)string{
// 过滤非法字符
NSCharacterSet *cs = [[ NSCharacterSet characterSetWithCharactersInString : kInputNumbers ] invertedSet ];
NSString *filtered = [[string componentsSeparatedByCharactersInSet :cs] componentsJoinedByString : @"" ];
BOOL basicTest = [string isEqualToString :filtered];
if (!basicTest) {
return NO ;
}
// 确定是否是删除键
_isDelete = string. length <= 0 ? YES : NO ;
if (textField == _textField1 ) {
// 这个方法确保手动点击某个 textfield 时可以实现跳到下一个
if (range. location == 5 ) {
[textField resignFirstResponder ];
_textField2 . enabled = YES ;
[ _textField2 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
if (range. location == 0 && _isDelete )
{
return NO ;
}
}
else if (textField == _textField2 ) {
if (range. location == 5 ) {
[textField resignFirstResponder ];
_textField3 . enabled = YES ;
[ _textField3 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
if (range. location == 0 && _isDelete ){
[textField resignFirstResponder ];
_textField1 . enabled = YES ;
[ _textField1 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
}
else if (textField == _textField3 ) {
if (range. location == 5 ) {
[textField resignFirstResponder ];
_textField4 . enabled = YES ;
[ _textField4 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
if (range. location == 0 && _isDelete ){
[textField resignFirstResponder ];
_textField2 . enabled = YES ;
[ _textField2 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
}
else {
if (range. location == 0 && _isDelete ){
[textField resignFirstResponder ];
_textField3 . enabled = YES ;
[ _textField3 becomeFirstResponder ];
textField. enabled = NO ;
return YES ;
}
return range. location <= 4 ;
}
return YES ;
}
/**
* 观察 textfield 改变之后的属性时调用这个方法,在这个方法里面控制往前面的格子里跳转(因为光标在第一个的时候没有回调方法,所以要在每个之前加上 @“ ” )
*
* @param notification 传入观察的对象
*/
- ( void )textFieldTextDidChange:( NSNotification *)notification
{
self . moneyLabel . hidden = YES ;
self . checkLeftBtn . enabled = NO ;
self . saveAndUseBtn . enabled = NO ;
UITextField *textField = ( UITextField *)[notification object ];
if (! _isDelete ) {
if (textField == _textField1 ) {
if (textField. text . length >= 5 ) {
_textField2 . enabled = YES ;
[textField resignFirstResponder ];
[ _textField2 becomeFirstResponder ];
_textField2 . text = @" " ;
textField. enabled = NO ;
}
} else if (textField == _textField2 ){
if (textField. text . length >= 5 ) {
_textField3 . enabled = YES ;
[textField resignFirstResponder ];
[ _textField3 becomeFirstResponder ];
_textField3 . text = @" " ;
textField. enabled = NO ;
}
} else if (textField == _textField3 ){
if (textField. text . length >= 5 ) {
_textField4 . enabled = YES ;
[textField resignFirstResponder ];
[ _textField4 becomeFirstResponder ];
_textField4 . text = @" " ;
textField. enabled = NO ;
}
}
}
if ( _textField1 . text . length + _textField2 . text . length + _textField3 . text . length + _textField4 . text . length >= 20 ) {
self . checkLeftBtn . enabled = YES ;
self . saveAndUseBtn . enabled = YES ;
}
}