在分组的 UITableView 中搜索
Posted
技术标签:
【中文标题】在分组的 UITableView 中搜索【英文标题】:Search in Grouped UITableView 【发布时间】:2013-05-10 12:42:36 【问题描述】:我是 Objective-C 开发的新手,我正在尝试过滤分组 UITableView 的内容。
这是我做的,但仍然没有工作:
- (void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", searchText];;
//activities is table that contains my objects that I display their contents in the table
self.filteredData = [activities filteredArrayUsingPredicate:resultPredicate];
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchScope:(NSInteger)searchOption
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
//activite is my object that I use to desplay its attribut in table
IPADActivity *activite ;
if (ThetableView == self.searchDisplayController.searchResultsTableView)
activite = [self.filteredData objectAtIndex:indexPath.row];
else
activite = [[objects
objectForKey:[objectsIndex objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
有什么建议
【问题讨论】:
您要在表中匹配的属性是什么? 感谢回复,我的对象activite包含一个名为“DESCRIPTIOIN”的属性,taht显示在桌子上。 尝试 DESCRIPTION CONTAINS[cd] %@", searchText 为你的谓词 【参考方案1】://
// ViewController.m
// SearchTut
//
#import "ViewController.h"
#import "SearchTableCell.h"
#import "XMLReader.h"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tablView;
@property (weak, nonatomic) IBOutlet UISearchBar *searchBr;
@property (nonatomic, strong) NSMutableArray *arrayList; //main table array
@property (nonatomic, strong) NSMutableArray *arrayFilteredList; //array with search results while user types in search bar
@property (nonatomic, strong) NSMutableDictionary *dictList; //need to manufacture an equivalent dictionary like below from the json array
/*
@
@"B" : @[@"Bear", @"Black Swan", @"Buffalo"],
@"C" : @[@"Camel", @"Cockatoo"],
@"D" : @[@"Dog", @"Donkey"],
@"E" : @[@"Emu"],
@"G" : @[@"Giraffe", @"Greater Rhea"],
@"H" : @[@"Hippopotamus", @"Horse"],
@"K" : @[@"Koala"],
@"L" : @[@"Lion", @"Llama"],
@"M" : @[@"Manatus", @"Meerkat"],
@"P" : @[@"Panda", @"Peacock", @"Pig", @"Platypus", @"Polar Bear"],
@"R" : @[@"Rhinoceros"],
@"S" : @[@"Seagull"],
@"T" : @[@"Tasmania Devil"],
@"W" : @[@"Whale", @"Whale Shark", @"Wombat"]
;
Refer: https://www.appcoda.com/ios-programming-index-list-uitableview/
*/
@property (nonatomic, strong) NSMutableDictionary *dictListFiltered; //dictionary when searched
@property (nonatomic, assign) BOOL isFiltered; //If user starts entering text in search bar, this flag is YES. If there is no text in search bar, this flag is NO.
@end
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
// Initialisers
self.tablView.dataSource = self;
self.tablView.delegate = self;
self.searchBr.delegate = self;
self.arrayList = [NSMutableArray array];
self.dictList = [NSMutableDictionary dictionary];
self.dictListFiltered = [NSMutableDictionary dictionary];
self.isFiltered = NO;
//Get and parse XML from file and load the result in array
NSString *strXMLPath = [[NSBundle mainBundle] pathForResource:@"List" ofType:@"xml"];
NSError *error;
NSString *strXML = [NSString stringWithContentsOfFile:strXMLPath encoding:NSUTF8StringEncoding error:&error];
NSDictionary *dict = [XMLReader dictionaryForXMLString:strXML error:&error];
NSDictionary *dictPriceList = [dict objectForKey:@"PRICELIST"];
NSArray *arrayLine = [dictPriceList objectForKey:@"LINE"];
NSMutableArray *arrayTempPriceList = [NSMutableArray array];
for (NSDictionary *dict in arrayLine)
[arrayTempPriceList addObject:dict];
self.arrayList = arrayTempPriceList;
NSLog(@"%@", self.arrayList);
//Create dictionary for sectioned table grouped with respect to PRICELISTCATEGORY value. PRICELISTCATEGORY value will be set in the section title. Logic to group table in sections is below
[self groupXMLinSectionsWithArray:arrayTempPriceList];
- (void)groupXMLinSectionsWithArray:(NSMutableArray *)arrayJson
if (arrayJson.count > 0) //added this condition to reset json during search.
for (NSDictionary *dict in arrayJson )
NSString *strPriceListCategory = [[dict objectForKey:@"PRICELISTCATEGORY"] objectForKey:@"text"];
if (self.isFiltered)
if ([[self.dictListFiltered allKeys] containsObject:strPriceListCategory])
NSMutableArray *arrayTemp = [self.dictListFiltered objectForKey:strPriceListCategory];
[arrayTemp addObject:dict];
[self.dictListFiltered setObject:arrayTemp forKey:strPriceListCategory];
else
NSMutableArray *arrayTemp = [[NSMutableArray alloc] initWithObjects:dict, nil];
[self.dictListFiltered setObject:arrayTemp forKey:strPriceListCategory];
else
if ([[self.dictList allKeys] containsObject:strPriceListCategory])
NSMutableArray *arrayTemp = [self.dictList objectForKey:strPriceListCategory];
[arrayTemp addObject:dict];
[self.dictList setObject:arrayTemp forKey:strPriceListCategory];
else
NSMutableArray *arrayTemp = [[NSMutableArray alloc] initWithObjects:dict, nil];
[self.dictList setObject:arrayTemp forKey:strPriceListCategory];
else //if search results yield no json array, then remove all objects from dictionary
[self.dictList removeAllObjects];
[self.dictListFiltered removeAllObjects];
[self.tablView reloadData];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
#pragma mark - TableView Datasource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
NSArray *arrayTemp = [NSArray array];
if (self.isFiltered)
NSArray *arrayListAllKeys = [self.dictListFiltered allKeys];
arrayTemp = [self.dictListFiltered objectForKey:[arrayListAllKeys objectAtIndex:section]];
else
NSArray *arrayListAllKeys = [self.dictList allKeys];
arrayTemp = [self.dictList objectForKey:[arrayListAllKeys objectAtIndex:section]];
return [arrayTemp count];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
SearchTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchTableCellId" forIndexPath:indexPath];
NSDictionary *dict;
if (self.isFiltered)
NSArray *arrayPriceListAllKeys = [self.dictListFiltered allKeys];
NSArray *arrayPrice = [self.dictListFiltered objectForKey:[arrayPriceListAllKeys objectAtIndex:indexPath.section]];
dict = [arrayPrice objectAtIndex:indexPath.row];
else
NSArray *arrayPriceListAllKeys = [self.dictList allKeys];
NSArray *arrayPrice = [self.dictList objectForKey:[arrayPriceListAllKeys objectAtIndex:indexPath.section]];
dict = [arrayPrice objectAtIndex:indexPath.row];
cell.lblBarCode.text = [[dict objectForKey:@"APNBARCODE"] objectForKey:@"text"];
cell.lblPackDescription.text = [[dict objectForKey:@"PACKDESCRIPTION"] objectForKey:@"text"];
cell.lblProduct.text = [[dict objectForKey:@"PRODUCT"] objectForKey:@"text"];
cell.lblProductName.text = [[dict objectForKey:@"PRODUCTNAME"] objectForKey:@"text"];
return cell;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
if (self.isFiltered)
return [[self.dictListFiltered allKeys] count];
else
return [[self.dictList allKeys] count];
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
NSString *price = @"";
if (self.isFiltered)
price = [[self.dictListFiltered allKeys] objectAtIndex:section];
else
price = [[self.dictList allKeys] objectAtIndex:section];
return price;
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
return 50.0;
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(8, 8, self.tablView.frame.size.width - 16, 30)];
//If you add a bit to x and decrease y, it will be more in line with the tableView cell (that is in iPad and landscape)
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake(0.5, 0.5);
label.font = [UIFont boldSystemFontOfSize:18];
label.text = sectionTitle;
// Create header view and add label as a subview
UIView *viewHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tablView.frame.size.width, 50)];
viewHeader.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1];
[viewHeader addSubview:label];
return viewHeader;
#pragma mark - SearchBar Delegates
- (void)updateSearchResults
//You can use the below commented code in case you need an exact match of the PRODUCT value text you entered in search bar
/*
NSMutableArray *searchResults = [self.arrayList mutableCopy];
NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"PRODUCT.text==[c] %@", strippedString];
searchResults = [[searchResults filteredArrayUsingPredicate:predicate] mutableCopy];
// hand over the filtered results to our search results table
self.arrayFilteredList = searchResults;
//NSLog(@"%@", self.arrayFilteredPriceList);
[self groupXMLinSectionsWithArray:self.arrayFilteredList];
*/
//Below code searches depending on Product / Product Name / APNBarCode values
NSString *searchText = self.searchBr.text;
NSMutableArray *searchResults = [self.arrayList mutableCopy];
NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *searchItems = nil;
if (strippedString.length > 0)
searchItems = [strippedString componentsSeparatedByString:@" "];
NSMutableArray *andMatchPredicates = [NSMutableArray array];
for (NSString *searchString in searchItems)
NSMutableArray *searchItemsPredicate = [NSMutableArray array];
// Below we use NSExpression represent expressions in our predicates.
// NSPredicate is made up of smaller, atomic parts: two NSExpressions (a left-hand value and a right-hand value)
// Product
NSExpression *lhsProduct = [NSExpression expressionForKeyPath:@"PRODUCT.text"];
NSExpression *rhsProduct = [NSExpression expressionForConstantValue:searchString];
NSPredicate *finalPredicateProduct = [NSComparisonPredicate
predicateWithLeftExpression:lhsProduct
rightExpression:rhsProduct
modifier:NSDirectPredicateModifier
type:NSContainsPredicateOperatorType
options:NSCaseInsensitivePredicateOption];
[searchItemsPredicate addObject:finalPredicateProduct];
// Product Name
NSExpression *lhsProductName = [NSExpression expressionForKeyPath:@"PRODUCTNAME.text"];
NSExpression *rhsProductName = [NSExpression expressionForConstantValue:searchString];
NSPredicate *finalPredicateProductName = [NSComparisonPredicate
predicateWithLeftExpression:lhsProductName
rightExpression:rhsProductName
modifier:NSDirectPredicateModifier
type:NSContainsPredicateOperatorType
options:NSCaseInsensitivePredicateOption];
[searchItemsPredicate addObject:finalPredicateProductName];
// APN Bar Code
NSExpression *lhsAPNBarCode = [NSExpression expressionForKeyPath:@"APNBARCODE.text"];
NSExpression *rhsAPNBarCode = [NSExpression expressionForConstantValue:searchString];
NSPredicate *finalPredicateAPNBarCode= [NSComparisonPredicate
predicateWithLeftExpression:lhsAPNBarCode
rightExpression:rhsAPNBarCode
modifier:NSDirectPredicateModifier
type:NSContainsPredicateOperatorType
options:NSCaseInsensitivePredicateOption];
[searchItemsPredicate addObject:finalPredicateAPNBarCode];
// AVERAGECOST
NSExpression *lhsPACKDESCRIPTION = [NSExpression expressionForKeyPath:@"PACKDESCRIPTION.text"];
NSExpression *rhsPACKDESCRIPTION = [NSExpression expressionForConstantValue:searchString];
NSPredicate *finalPredicatePACKDESCRIPTIONt = [NSComparisonPredicate
predicateWithLeftExpression:lhsPACKDESCRIPTION
rightExpression:rhsPACKDESCRIPTION
modifier:NSDirectPredicateModifier
type:NSContainsPredicateOperatorType
options:NSCaseInsensitivePredicateOption];
[searchItemsPredicate addObject:finalPredicatePACKDESCRIPTIONt];
// at this OR predicate to our master AND predicate
NSCompoundPredicate *orMatchPredicates = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
[andMatchPredicates addObject:orMatchPredicates];
// match up the fields of the Product object
NSCompoundPredicate *finalCompoundPredicate =
[NSCompoundPredicate andPredicateWithSubpredicates:andMatchPredicates];
searchResults = [[searchResults filteredArrayUsingPredicate:finalCompoundPredicate] mutableCopy];
// hand over the filtered results to our search results table
self.arrayFilteredList = searchResults;
//NSLog(@"%@", self.arrayFilteredPriceList);
[self groupXMLinSectionsWithArray:self.arrayFilteredList];
//This method gets called when user starts entering text in search bar
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
if (searchText.length == 0)
self.isFiltered = NO;
[self.dictList removeAllObjects];
[self groupXMLinSectionsWithArray:self.arrayList];
[self.tablView reloadData];
else
self.isFiltered = YES;
self.arrayFilteredList = [NSMutableArray new];
[self.dictListFiltered removeAllObjects];
[self updateSearchResults];
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
[searchBar resignFirstResponder];
[self.dictList removeAllObjects];
[self groupXMLinSectionsWithArray:self.arrayList];
[self.tablView reloadData];
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
[searchBar resignFirstResponder];
[self.tablView reloadData];
@end
以上代码逻辑基于 json 数组,字典包含在数组中,我们根据 PRICELISTCATEGORY 值创建部分
[
"PRODUCT":
"text": "GELDCMFRAME"
,
"PRODUCTMAJORGROUP":
"text": "IC"
,
"PRICELISTCATEGORY":
"text": "GELDISP"
,
"APNBARCODE":
"text": "931000"
,
"PACKDESCRIPTION":
"text": "Some Description"
,
"PRODUCTNAME":
"text": "Description"
and so on
, and so on
]
请参阅下面的屏幕截图以获取搜索结果
【讨论】:
以上是关于在分组的 UITableView 中搜索的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableView 单元格中定位 UIImageViews
如何在同一个视图中呈现 UITableView 及其详细视图