IOS5基础之十三-----实现搜索栏

2023-10-12 18:50
文章标签 基础 实现 搜索 十三 ios5

本文主要是介绍IOS5基础之十三-----实现搜索栏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

为什么要把搜索栏单独写,主要是这里牵涉到一个深层可变副本。在这里为什么要用这个~~~~你迷茫吗?

我也很迷茫哈哈~~~~~~

该项目是请一个项目的加强版,虽然只是多了一个搜索控件,可是却多了许多步骤。

上次公司需要添加一个字段。也就是在数据库中新增一个字段。我排的时间相对长了一点,受到众人笑话。可是当你对系统的复杂性了解后,你会知道特别时在数据库增加字段时带来了很多的问题。并且我这个字段几乎整个项目的所有表都要增加。因为每张表的关联性,并且有些地方要添加,有的地方使用存储过程,有的是创建临时表,如果要时间短,是可以完成,但是谁有知道那些地方没有修改,当过了一段时间后,就会有一段垃圾数据出现,那时也只有去修改数据库了,哈哈废话一段!!!!也许还是我的能力有限。

前面我使用了多数组的字段,其中字母表中的每个字母都占用一个数组。该字典是不可改变的。这就意味着不能从字典添加和删除值。它包含的数组也是如此。所以要创建两个字典,一个包含完整数据集的不可改变的字典,一个可以从中删除行的可变的字典副本。

复习一下,浅层复制和深层复制

浅层复制:不复制引用对象,新复制的对象值指向现有的引用对象。

深层复制:将复制所用的引用对象。

NSDictionary遵循NSMutableCopying协议,该方法创建的是一个浅层副本。但是引用对象是不能删除的,所以是无法删除对象的。需要一个类别去存放数组的字典的副本。


添加类别后 项目导航变成


在头文件中做一个接口返回NSMutbleDictionary类型的方法

#import <Foundation/Foundation.h>

@interface NSDictionary (MutableDeepCopy)

-(NSMutableDictionary *) mutableDeepCopy;

@end


实现改方法

- (NSMutableDictionary *)mutableDeepCopy {

    NSMutableDictionary *returnDict = [[NSMutableDictionary alloc]

                                       initWithCapacity:[self count]];

    NSArray *keys = [self allKeys];

    for (id key in keys) {

        id oneValue = [self valueForKey:key];

        id oneCopy = nil;

        

        if ([oneValue respondsToSelector:@selector(mutableDeepCopy)])

            oneCopy = [oneValue mutableDeepCopy];

        else if ([oneValue respondsToSelector:@selector(mutableCopy)])

            oneCopy = [oneValue mutableCopy];

        if (oneCopy == nil)

            oneCopy = [oneValue copy];

        [returnDict setValue:oneCopy forKey:key];

    }

    return returnDict;

}

用一个数组存储这个这个字典。遍历并且判断对象如果没有响应mutableDeepCopy消息,那么它将创建可变副本,否则就创建常规副本。

for (id  key in keys)称为快速枚举类似C#中的foreach()方法。NSDictionary 、NSArray、NSSet都支持快速枚举。


现在头文件修改为

#import <UIKit/UIKit.h>


@interface BIDViewController :UIViewController

<UITableViewDataSource,UITableViewDelegate>


@property (strong,nonatomicIBOutlet UITableView *table;   //指向输出口视图

@property (strong,nonatomicIBOutlet UISearchBar *search;  //指向输出口搜索栏

@property (strong,nonatomicNSDictionary *allNames;        //字典存放所有的数据集

@property (strong,nonatomicNSMutableDictionary *names;    //将存有那些与当前搜索条件匹配的数据集

@property (strong,nonatomicNSMutableArray *keys;          //将存有索引值和分区名称

@property (assignnonatomicBOOL isSearching;             //是否在使用搜索栏

-(void)resetSearch;                                        //复制数据

-(void)handleSearchForTerm:(NSString *)searchTerm;          //实现搜索的方法


@end

实现方法如下

#import "BIDViewController.h"

#import "NSDictionary+MutableDeepCopy.h"


@implementation BIDViewController

@synthesize table;

@synthesize search;

@synthesize allNames;

@synthesize names;

@synthesize keys;

@synthesize isSearching;


#pragma mark

#pragma mark Custom Methods

-(void)resetSearch

{

    self.names =[self.allNames mutableDeepCopy];

    NSMutableArray *keyArray= [[NSMutableArray allocinit];

    [keyArray addObject:UITableViewIndexSearch];

    [keyArray addObjectsFromArray:[[self.allNames allKeyssortedArrayUsingSelector:@selector(compare:)]];

    self.keys=keyArray;

}


-(void) handleSearchForTerm:(NSString *)searchTerm

{

    NSMutableArray *sectionsToRemove=[[NSMutableArray allocinit];//创建一个数组,存放我们找到的空分区。

  

    [self resetSearch];

    for(NSString *key in self.keys)

    {

        NSMutableArray *array=[names valueForKey:key];//存放需要从names数组中删除的值的数组

        NSMutableArray *toRemove=[[NSMutableArray alloc]init];

       

        for(NSString *name in array)

        {

            //循环使用一个字符串中子字符串位置的NSString的方法。并且返回一个NSRange结构,如果返回的包含了NSNotFound就添加到要删除的对象数组中

            if ([name rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound

            {

                [toRemove addObject:name];

            }

        }

        if ([array count]==[toRemove count]) {

            [sectionsToRemove addObject:key];

        }

        [array removeObjectsInArray:toRemove];//从此分区中删除不匹配的对称

    }

     //删除空分区 并告知重新加载数据

    [self.keys removeObjectsInArray:sectionsToRemove];

    //[sectionsToRemove release];

    [table reloadData];

}




- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.

}


#pragma mark - View lifecycle


//初始化数据

- (void)viewDidLoad

{

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    NSString *path= [[NSBundle mainBundlepathForResource:@"sortednames"ofType:@"plist"];

    NSDictionary *dict = [[NSDictionary alloc]initWithContentsOfFile:path];

    self.allNames=dict;

    [self resetSearch];

    [table reloadData];

    [table setContentOffset:CGPointMake(0.0,44.0animated:NO];//设置表中内容的偏移量

    

}


- (void)viewDidUnload

{

    [super viewDidUnload];

    // Release any retained subviews of the main view.

    // e.g. self.myOutlet = nil;

    self.names=nil;

    self.keys=nil;

    self.allNames=nil;

    self.table=nil;

    self.search=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 Table View Data Source Methods

//指定分区的数量

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

    return ([keys count])>0?[keys count]:1;

}


//用于计算特定分区中的行数,检索与讨论中的分区对应的数组。并从该数组中返回行的数量。

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    if ([keys count]==0) {

        return 0;

    }

    NSString *key =[keys objectAtIndex:section];

    NSArray *nameSection=[names objectForKey:key];

    return [nameSection count];

}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    

    NSUInteger section=[indexPath section];

    NSUInteger row=[indexPath row];

    

    NSString *key =[keys objectAtIndex:section];

    NSArray *nameSection=[names objectForKey:key];

    

    static NSString *SectionsTableIdentifier=@"SectionsTableIdentifiler";

    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];

    if (cell==nil) {

        cell=[[UITableViewCell allocinitWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier];

    }

    cell.textLabel.text=[nameSection objectAtIndex:row];

    return cell;

}


//为每个分区指定一个可选的标题值,然后只返回这一组的字母就可以了

-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

{

    if ([keys count]==0) {

        return nil;

    }

    NSString *key=[keys objectAtIndex:section];

    if (key==UITableViewIndexSearch) {

        return nil;

    }

    return  key;

}


//添加索引的方法

-(NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView

{

    if (isSearching)

        return nil;

    return keys;

}


#pragma mark -

#pragma mark Table View Delegate Methods

- (NSIndexPath *)tableView:(UITableView *)tableView

  willSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    [search resignFirstResponder];//如果用户在使用搜索栏时单击一行,我们希望键盘不再起作用。

    isSearching = NO;

    search.text = @"";

    [tableView reloadData];

    return indexPath;

}


#pragma mark -

#pragma mark Search Bar Delegate Methods

//当用户单击键盘上的返回按钮或搜索按钮时,调用,此方法从搜索栏获取搜索短语。并调用搜索方法。

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {

    NSString *searchTerm = [searchBar text];

    [self handleSearchForTerm:searchTerm];

}


//实时搜索,只要搜索栏中的短语发生变化都重新搜索,这个是需要设备的高性能。

- (void)searchBar:(UISearchBar *)searchBar

    textDidChange:(NSString *)searchTerm {

    if ([searchTerm length] == 0) {

        [self resetSearch];

        [table reloadData];

        return;

    }

    [self handleSearchForTerm:searchTerm];

}


//取消按钮的触发的事件

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {

    isSearching = NO;

    search.text = @"";

    [self resetSearch];

    [table reloadData];

    [searchBar resignFirstResponder];

}


- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {

    isSearching = YES;

    [table reloadData];

}


- (NSInteger)tableView:(UITableView *)tableView

sectionForSectionIndexTitle:(NSString *)title

               atIndex:(NSInteger)index {

    NSString *key = [keys objectAtIndex:index];

    if (key == UITableViewIndexSearch) {

        [tableView setContentOffset:CGPointZero animated:NO];

        return NSNotFound;

    } else return index;

}


@end


提到一个搜索的放大器功能。

3个步骤:

a。向keys数组添加一个特殊值以指示我们需要一个放大镜。

-(void)resetSearch

{

    self.names =[self.allNames mutableDeepCopy];

    NSMutableArray *keyArray= [[NSMutableArray allocinit];

    [keyArray addObject:UITableViewIndexSearch];

    [keyArray addObjectsFromArray:[[self.allNames allKeyssortedArrayUsingSelector:@selector(compare:)]];

    self.keys=keyArray;

}


b。必须阻止IOS在表格中显示该特殊值的部分标题。

-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

{

    if ([keys count]==0) {

        return nil;

    }

    NSString *key=[keys objectAtIndex:section];

    if (key==UITableViewIndexSearch) {

        return nil;

    }

    return  key;

}

c。告诉表格在该项被选中时滚至顶部。

- (NSInteger)tableView:(UITableView *)tableView

sectionForSectionIndexTitle:(NSString *)title

               atIndex:(NSInteger)index {

    NSString *key = [keys objectAtIndex:index];

    if (key == UITableViewIndexSearch) {

        [tableView setContentOffset:CGPointZero animated:NO];

        return NSNotFound;

    } else return index;

}


遇到很多问题。

1。在视图页面的时候,没有在UIView中添加一个View,直接将Search Bar 拖进去。无法修改其长度。

2。 self.names =[self.allNames mutableDeepCopy];的时候mutableCopy,报数组不能变成可变的。

3。说error code。反复验证对比没有发现错误,后来网上一查,说要重启电脑错误自动消失,抓狂,搞的我花费了很长的事件认真核对代码。

其实代码是出来了,还是有很多地方不是很理解。要抄出来还是挺费劲的,估计是自己比较弱,哈哈。虽然花了2~3天的时间。这里还是要重复多看看。

这篇关于IOS5基础之十三-----实现搜索栏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/197778

相关文章

Nginx 配置跨域的实现及常见问题解决

《Nginx配置跨域的实现及常见问题解决》本文主要介绍了Nginx配置跨域的实现及常见问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来... 目录1. 跨域1.1 同源策略1.2 跨域资源共享(CORS)2. Nginx 配置跨域的场景2.1

Python中提取文件名扩展名的多种方法实现

《Python中提取文件名扩展名的多种方法实现》在Python编程中,经常会遇到需要从文件名中提取扩展名的场景,Python提供了多种方法来实现这一功能,不同方法适用于不同的场景和需求,包括os.pa... 目录技术背景实现步骤方法一:使用os.path.splitext方法二:使用pathlib模块方法三

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM