(4) iphone 开发 在表视图(UITableView) 中利用UISearchBar实现数据的搜索,视图的多功能化...

程序概括:

1.对数据进行过滤查找。2.最上头要有一个SearchBar,对输入数据进行检索,点击SearchBar上的cancer按钮退出屏幕键盘并清除输入框内的数据。3.索引栏:在索引最上方添加一个扩大镜(UITableViewIndexSearch)。点击扩大镜的作用就是让SearchBar出现在屏幕最上方。

程序的样子:

(4) iphone 开发 在表视图(UITableView) 中利用UISearchBar实现数据的搜索,视图的多功能化...(4) iphone 开发 在表视图(UITableView) 中利用UISearchBar实现数据的搜索,视图的多功能化...

再罗嗦几句:此程序的数据存在plist文件中,其中有一个值得注意的一点是:本程序利用了类别(category,在类外定义其方法而不使用其子类)来实现了字典的深层复制。

其余的就靠仔细阅读了

具体细节代码中注释的也很详细,直接上代码:

1)NSDictionary的类别,深层复制

MutableDeepCopy.h

#import <Foundation/Foundation.h> @interface NSDictionary (MutableDeepCopy) -(NSMutableDictionary*)mutableDeepCopy; @end

MutableDeepCopy.m


#import "MutableDeepCopy.h" @implementation NSDictionary (MutableDeepCopy) -(NSMutableDictionary*)mutableDeepCopy{ NSMutableDictionary *mudic=[[NSMutableDictionary alloc] initWithCapacity:[self count]]; //获取字典里的所有键进行便利 for (id key in [self allKeys]) { //这里用id的原因是此时并不知道value里是否还含有其他类型数据(字典,数组:非字符串)。 id value=[self valueForKey:key]; id tmpvalue=nil; if ([value respondsToSelector:@selector(mutableDeepCopy)]) { tmpvalue=[value mutableDeepCopy]; }else if ([value respondsToSelector:@selector(mutableCopy)]) { tmpvalue=[value mutableCopy]; } [mudic setValue:tmpvalue forKey:key]; } return mudic; } @end

2)控制器.h

#import <UIKit/UIKit.h> @interface iphone0408UITableViewSearchViewController : UIViewController <UITableViewDataSource,UITableViewDelegate,UISearchBarDelegate> { UITableView *MyUITableView; UISearchBar *MySearchBar; BOOL issearching; } @property (nonatomic,retain) NSDictionary *localresource; @property (nonatomic,retain) NSMutableDictionary *Myresource; @property (nonatomic ,retain) NSMutableArray * Mykey; @property (nonatomic, strong) IBOutlet UISearchBar *MySearchBar; @property (nonatomic, strong) IBOutlet UITableView *MyUITableView; -(void)resetTableView; -(void)SearchData: (NSString*) searchtext; @end

控制器.m


#import "iphone0408UITableViewSearchViewController.h" #import "MutableDeepCopy.h" @implementation iphone0408UITableViewSearchViewController @synthesize MySearchBar; @synthesize MyUITableView; @synthesize localresource; @synthesize Myresource; @synthesize Mykey; - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark- #pragma mark NO.2 Custom Method /*此方法做了三件事 1.得到将字典数据copy成可变字典的数据。2.得到数据的可变类型的键(key)。3.在索引最上方加了一个小的扩大镜(UITableViewIndexSearch),用于还原图表初始位置。 */ -(void)resetTableView{ //得到可变字典(数据)深层复制 NSMutableDictionary *Mdic=[self.localresource mutableDeepCopy]; //付给全局变量 self.Myresource=Mdic; //这里就需要注意了:需要把扩大镜(UITableViewIndexSearch)也加到Mykey里 NSMutableArray *key=[[NSMutableArray alloc] init]; //先向key里添加第一个值,保证其在第一的位置(保证扩大镜在索引的最上头)。 [key addObject:UITableViewIndexSearch]; [key addObjectsFromArray:[[self.Myresource allKeys] sortedArrayUsingSelector:@selector(compare:)]]; self.Mykey=key; // [self.MyUITableView reloadData]; } #pragma mark NO.6 /*搜索删除不符合的值。先准备一个空的可变key容器用于储存不符合的key,接下来创建两个可变数组容器,一个用于存储key所对应的值(数组),另一个为空,用于存储需要移除的值。 */ -(void)SearchData:(NSString *)searchtext{ //准备储存要删掉的key NSMutableArray *removekey=[[NSMutableArray alloc] init]; for (NSString * key in self.Mykey) { NSMutableArray *localarr=[self.Myresource valueForKey:key]; //准备存储要删掉的key里的数组 NSMutableArray *removearr=[[NSMutableArray alloc] init]; for (NSString * tmpvalue in localarr) { if ([tmpvalue rangeOfString:searchtext options:NSCaseInsensitiveSearch].location==NSNotFound ) { [removearr addObject:tmpvalue]; } } if ([localarr count] == [removearr count]) { [removekey addObject:key]; } //移除不符合的值 [localarr removeObjectsInArray:removearr]; } //移除不符合的值(key所对应的值(整个数组)) [self.Mykey removeObjectsInArray:removekey]; //重新加载(刷新)。 [MyUITableView reloadData]; } #pragma mark - View lifecycle #pragma mark NO.1 run - (void)viewDidLoad { NSString *path=[[NSBundle mainBundle] pathForResource:@"PropertySearchList" ofType:@"plist"]; NSDictionary *dic=[[NSDictionary alloc] initWithContentsOfFile:path]; self.localresource=dic; //调用已经写好的方法 [self resetTableView]; //将表视图向上偏移(伸长)44.0 目的是将搜索栏(UISearchBar)盖住 [self.MyUITableView setContentOffset:CGPointMake(0.0, 44.0) animated:NO]; [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)viewDidUnload { [self setMyUITableView:nil]; [self setMySearchBar:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); } #pragma mark- #pragma mark NO.3 TableVeiw Data Source Method /* 1.分区数。2.每个分区的行数。3.cell显示。4.分区标题。5.索引 */ //返回分区个数 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return [self.Mykey count]>0?[Mykey count]:1; } //返回所在分区的行数 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ if ([self.Mykey count]==0) { return 0; } NSString *key=[self.Mykey objectAtIndex:section]; NSArray *arr=[self.Myresource valueForKey:key]; return [arr count]; } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ NSInteger row=[indexPath row]; NSInteger section=[indexPath section]; static NSString *[email protected]"DongStone"; UITableViewCell *cell=[MyUITableView dequeueReusableCellWithIdentifier:MyTagName]; if (cell==nil) { cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyTagName]; } NSString *key=[self.Mykey objectAtIndex:section]; NSArray *arr=[self.Myresource valueForKey:key]; cell.textLabel.text=[arr objectAtIndex:row]; return cell; } //设置分区标题三种情况 1.屏幕显示范围内没有分区。2.key的值正好等于下标为零的放大镜查找(UITableViewIndexSearch)。3.正常返回数据分区标题。 -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ if ([Mykey count]==0) { return nil; } //注意:此行代码必须在此处,如果拿到上面,当key无值时,程序会crash,内存泄露。 NSString *key=[Mykey objectAtIndex:section]; if (key==UITableViewIndexSearch) { return nil; } return key; } ////索引,当issearching为YES时说明searchbar被点击----->[ 索引 ] 被nil,隐藏 -(NSArray*)sectionIndexTitlesForTableView:(UITableView *)tableView{ if (issearching) { return nil; } return self.Mykey; } #pragma mark- #pragma mark NO.4 TableView Delegate Method //点击uitableview触发此方法。 -(NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{ [MySearchBar resignFirstResponder]; [email protected]""; issearching=NO; [MyUITableView reloadData]; return indexPath; } #pragma mark- #pragma mark NO.5 Search Bar Delegate Method //点击search按钮 //从UISearchBar输入框中提取内容调用SearchData方法进行查找 -(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{ NSString *mysearch=[searchBar text]; [self SearchData:mysearch]; } //自动搜索 -(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{ if ([searchText length]==0) { [self resetTableView]; [MyUITableView reloadData]; return; } [self SearchData:searchText]; } //点击Cancle按钮 //清除记录退回屏幕键盘,返回初始状态。显示索引。 -(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{ issearching=NO; [email protected]""; //当重新输入时,重新加载,此前就是落下了这一步,让我很头疼。 [self resetTableView]; [MyUITableView reloadData]; [searchBar resignFirstResponder]; } //点击输入框时被触发 -(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{ issearching=YES; [MyUITableView reloadData]; } //点击索引会调用此方法。点击扩大镜UITableViewIndexSearch让searchbar出现(因为扩大镜在执行resettableview方法时把其下标设为0,加入key的,所以执行if语句会进入)。 -(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{ NSString *key=[self.Mykey objectAtIndex:index]; if (key==UITableViewIndexSearch) { [MyUITableView setContentOffset:CGPointZero animated:NO]; return NSNotFound; } return index; } @end

3) 创建plist文件方法 点击连接:(6) iphone 开发 从应用程序看UITableView的:分组,分区,索引,工作原理及其变换法则,plist文件数据定义规则