要实现一个搜索功能,筛选功能。
用系统自带的UISearchController有一些问题,不够灵活, 所以使用自定义的一个UITextField视图
第一种方法:
要在每次输入字符的时候都去更新匹配到的结果,从而去刷新列表视图(UITableView)。
主要的方法是实现在UITextField的代理方法中
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
下面对该方法进行解释:
上面方法中返回YES则输入字符之后会变,返回NO的话输入字符textField的内容不会变。
textField:就是输入框,打印textField.text显示的内容是输入字符之前的内容。新输入的字符还没有存储在textField.text中。
string:就是输入的字符。
range:刚开始输入第一个字符的时候range.location为0,输入第二个字符的时候range.location为1,由此可见range可以表示新插入的字符的位置,即光标所在的位置。
所以就好办了:可以把string拼接到textField.text中去。
但是又有一个问题:如果不是在最后输入的,而是在textField的中间的位置输入的字符,那么就需要根据range从指定的位置去插入字符了。
注:
用到两个属性:self.isSearch和self.searchStr。
isSearch表示显示原本的数据列表还是搜索的数据列表,searchStr表示输入框中的搜索内容。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
/*
当全部删除输入框内容的时候,要显示原来的列表,不显示搜索结果列表。通过在控制台打印NSStringFromRange(range) 发现range为{0, 1},所以要在range为{0, 1}的时候做处理。
判断是显示原本的列表还是显示搜索后的列表,如果range为{0, 1}则self.isSearch = NO显示原本的列表,否则显示搜索的列表。
*/
if (range.location == 0 && range.length == 1) {
self.isSearch = NO;
self.searchStr = @"";
[self.searchList removeAllObjects];
[self.tableView reloadData];
return YES;
}
self.isSearch = YES;
UITextRange *selectedRange = textField.markedTextRange;
if (selectedRange == nil) {
/*
高亮状态的字符串为空,也就是输入数字字母的情况。
这是正常的情况。
*/
//获取搜索的内容
NSMutableString *searchString = [NSMutableString stringWithString:textField.text];
if ([string isEqualToString:@""]) {
//这是删除字符
[searchString replaceCharactersInRange:range withString:string];
} else {
//插入字符
[searchString insertString:string atIndex:range.location];
}
self.searchStr = searchString;
//谓词
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", searchString];
//判断搜索数组是否为空
if (self.searchList != nil) { [self.searchList removeAllObjects]; }
//使用谓词过滤数据
self.searchList = [NSMutableArray arrayWithArray:[self.dataArray filteredArrayUsingPredicate:predicate]];
//刷新
[self.tableView reloadData];
} else {
//有输入的拼音 还没有选定的情况。
NSString *newText = [textField textInRange:selectedRange];
if (newText.length > 0) {
if ([self judgeInputIsChinese:string]) {
//
//获取搜索的内容
NSMutableString *searchString = [NSMutableString stringWithString:textField.text];
if ([string isEqualToString:@""]) {
//这是删除字符
[searchString replaceCharactersInRange:range withString:string];
} else {
//插入字符
[searchString replaceCharactersInRange:NSMakeRange(range.location, newText.length) withString:@""];
[searchString insertString:string atIndex:range.location];
}
self.searchStr = searchString;
//谓词
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[c] %@", searchString];
//判断搜索数组是否为空
if (self.searchList != nil) { [self.searchList removeAllObjects]; }
//使用谓词过滤数据
self.searchList = [NSMutableArray arrayWithArray:[self.dataArray filteredArrayUsingPredicate:predicate]];
//刷新
[self.tableView reloadData];
}
}
}
return YES;
}
有一个问题:
输入数字和英文没问题,但是输入汉字的情况不一样, 输入汉字时,输入拼音只要不按空格或者选定,如果拼接输入框中的待定的拼音拼接到textfield.text中是不对的。
在网上查找到一个方法:
在用UITextField替代搜索控件时,搜索输入汉字时,没输入一个英文拼都触发了textFieldDidChange,而我想等选择完汉字或英文字符后在触发,
需要再textFieldDidChange添加一个判断
UITextRange *rang = textField.markedTextRange; // 获取非=选中状态文字范围
if (rang == nil) { // 没有非选中状态文字.就是确定的文字输入
}
判断输入字符是否为汉字
- (BOOL)judgeInputIsChinese:(NSString *)textStr{
NSString *regex = @"(^[\u4e00-\u9fa5]+$)";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
BOOL isMatch = [pred evaluateWithObject:textStr];
return isMatch;
}
第二种方法:
非常简单,textField添加一个方法。
[textField addTarget:self action:@selector(searchAction:) forControlEvents:UIControlEventEditingChanged];
- (void)searchAction:(UITextField *)sender {
NSLog(@"---%@",sender.text);
}
网友评论