/**
最近做的項(xiàng)目中需要到一個(gè)仿照網(wǎng)易云音樂的搜索功能,我把它抽離出來(lái)供大家分享,有一些寫的不好的地方,歡迎大家指正
我在這里用朋友的測(cè)試接口展示數(shù)據(jù),僅供測(cè)試使用,請(qǐng)勿進(jìn)行商業(yè)用途
/
/
這里會(huì)講一下基本的搜索功能的搭建,首先是當(dāng)點(diǎn)擊搜索框的時(shí)候,調(diào)起鍵盤并顯示搜索歷史記錄,然后在點(diǎn)擊記錄時(shí)返回搜索數(shù)據(jù)
當(dāng)點(diǎn)擊鍵盤時(shí)候,顯示匹配到的關(guān)鍵字,點(diǎn)擊字段返回?cái)?shù)據(jù)并將該字段存入到歷史記錄中
雖然搜索功能很小很簡(jiǎn)單,但是不細(xì)心的話也會(huì)出現(xiàn)很多bug,我會(huì)把我想到的一些注意事項(xiàng)寫在項(xiàng)目中,歡迎大家指正補(bǔ)充
**/
效果圖如下:

我們先來(lái)分析一下:首先點(diǎn)擊搜索框的時(shí)候,彈出鍵盤,顯示歷史記錄;點(diǎn)擊鍵盤開始輸入時(shí),需要匹配關(guān)鍵字;點(diǎn)擊鍵盤上的搜索,點(diǎn)擊歷史記錄,點(diǎn)擊匹配到的關(guān)鍵字的時(shí)候都要返回值,然后界面刷新UI。
我們需要搭建一個(gè)本地?cái)?shù)據(jù)庫(kù)來(lái)存儲(chǔ)搜索的歷史記錄
DataBase.h
<pre>
import <Foundation/Foundation.h>
import "SearchModel.h"
@interface DataBase : NSObject
/**
- 創(chuàng)建單例接口
*/
- (DataBase *)shareDataBase;
pragma mark -
/**
- 收藏接口
*/
- (void)saveModel:(SearchModel )model;
/*
- 判斷是否已經(jīng)收藏
*/
- (BOOL)isHadSaveModel:(SearchModel )model;
/*
- 獲取收藏的所有數(shù)據(jù)
*/
- (NSArray )selectAllModel;
/*
- 刪除一個(gè)收藏
*/
- (void)deleteOneModelByStr:(NSString *)str;
@end
</pre>
.m
<pre>
import "DataBase.h"
import "FMDB.h"
@interface DataBase ()
@property (nonatomic, strong) FMDatabase *db;
@end
@implementation DataBase
// 創(chuàng)建單例
- (DataBase *)shareDataBase
{
static DataBase *single = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
single = [[DataBase alloc] init];
[single creatDataBase];
});
return single;
}
// 創(chuàng)建數(shù)據(jù)庫(kù)
-
(void)creatDataBase
{
// 在Documents文件夾下創(chuàng)建db.sqlite
NSString *dbPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"db.splite"];// 初始化
self.db = [FMDatabase databaseWithPath:dbPath];
// 打開數(shù)據(jù)庫(kù)
[self.db open];
// 創(chuàng)建表格
[self creatTable];
}
(void)creatTable
{
BOOL isSuccess = [self.db executeUpdate:@"create table if not exists MV(id integer primary key autoincrement, historyStr text)"];
NSLog(@"%@", isSuccess ? @"表格創(chuàng)建成功":@"表格創(chuàng)建失敗");
}(BOOL)isHadSaveModel:(SearchModel *)model
{
FMResultSet *set = [self.db executeQuery:@"select * from MV where historyStr = ?", model.historyStr];
while ([set next]) {
NSString *historyStr = [set stringForColumn:@"historyStr"];
if ([model.historyStr isEqualToString:historyStr]) {
return YES;
}
}
return NO;
}-
(void)saveModel:(SearchModel *)model
{
BOOL isSuccess = [self.db executeUpdate:@"insert into MV(historyStr) values (?)", model.historyStr];NSLog(@"%@", isSuccess ? @"收藏成功":@"收藏失敗");
} (NSArray *)selectAllModel
{
FMResultSet *set = [self.db executeQuery:@"select *from MV"];
NSMutableArray *arr = [NSMutableArray array];
while ([set next]) {
NSString *historyStr = [set stringForColumn:@"historyStr"];
SearchModel *model = [[SearchModel alloc] init];
model.historyStr = historyStr;
[arr addObject:model];
}
return arr;
}-
(void)deleteOneModelByStr:(NSString *)str
{
BOOL isSuccess = [self.db executeUpdate:@"delete from MV where historyStr = ?", str];NSLog(@"%@", isSuccess ? @"刪除成功":@"刪除失敗");
}
</pre>
搭建一下主界面,這里我是用一個(gè)collectionView寫的. 實(shí)現(xiàn)代理方法
<pre>
/**
- 創(chuàng)建一個(gè)collectionView
*/
-
(void)creatCollectionView
{
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
self.myCollection = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 60, ScreenWidth, ScreenHeight - 60) collectionViewLayout:flowLayout];
self.myCollection.backgroundColor = [UIColor orangeColor];
_myCollection.dataSource = self;
_myCollection.delegate = self;
[self.view addSubview:_myCollection];
[_myCollection registerClass:[UserCollectionViewCell class] forCellWithReuseIdentifier:cellID];
[self.view addSubview:_myCollection];// 在collection上添加一個(gè)搜索框
self.searchTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 20, ScreenWidth-100, 40)];
_searchTextField.placeholder = @"??輸入關(guān)鍵字查詢";
_searchTextField.textColor = [UIColor redColor];
_searchTextField.borderStyle = UITextBorderStyleRoundedRect;
[self.view addSubview:_searchTextField];
// 設(shè)置textfield的return鍵為搜索鍵
_searchTextField.returnKeyType = UIReturnKeySearch;
// 設(shè)置textfield的代理
_searchTextField.delegate = self;
}
</pre>
然后我們需要再寫一個(gè)tableView,用來(lái)展示歷史記錄和匹配到的關(guān)鍵字
<pre>
**
- table的cell有兩種,一種是歷史的cell,一種是匹配關(guān)鍵字的cell,這里我建了兩個(gè)cell
- 分別展示,根據(jù)傳入的一個(gè)標(biāo)識(shí)分別創(chuàng)建(因?yàn)閮蓚€(gè)cell只有一個(gè)button的區(qū)別,也可以創(chuàng)建一
- 個(gè)cell再來(lái)控制button的顯隱性。不過我特么就是想創(chuàng)建兩個(gè))
*/
-
(void)creatTableViewWithStr:(NSString *)str
{
self.myTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 60, ScreenWidth, ScreenHeight-60) style:(UITableViewStylePlain)];
if ([str isEqualToString:@"history"]) {
[_myTable registerNib:[UINib nibWithNibName:@"HistoryTableViewCell" bundle:nil] forCellReuseIdentifier:tableCellId];
}else {
[_myTable registerNib:[UINib nibWithNibName:@"KeyWordTableViewCell" bundle:nil] forCellReuseIdentifier:tableCellId];
} _myTable.delegate = self;
_myTable.dataSource = self;// 當(dāng)tableView滑動(dòng)時(shí)收起鍵盤
_myTable.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
// 取消tableView的分割線
_myTable.separatorStyle = UITableViewCellSeparatorStyleNone;[self.view addSubview:_myTable];
}
</pre>
在這里看一下我在主控制器中所定義的屬性,都是要用到的。
<pre>
@interface ViewController ()<UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UICollectionView *myCollection; //
@property (nonatomic, strong) UITableView *myTable; //
@property (nonatomic, strong) UITextField *searchTextField; // 搜索框
@property (nonatomic, strong) NSMutableArray dataSource; // cell數(shù)據(jù)源
@property (nonatomic, strong) NSMutableArray textFieldDataSource; // 匹配字段數(shù)據(jù)源
@property (nonatomic, strong) NSMutableArray historyDataSource; // 搜索歷史數(shù)據(jù)源
/我在這里用一個(gè)替換字段接收請(qǐng)求下來(lái)的匹配字段的數(shù)據(jù)。。不這樣做的話,在匹配字段返回的cell時(shí),如果是在漢語(yǔ)模式下編輯,在沒有確定輸入字段時(shí),此時(shí)已經(jīng)匹配到了字段,但是如果點(diǎn)擊的時(shí)候,在點(diǎn)擊事件中,原來(lái)的數(shù)據(jù)源是空的,可能是我在哪里清空了原來(lái)的數(shù)據(jù)源,我沒有找到,只能用一個(gè)新的數(shù)據(jù)源來(lái)替代。英文模式下輸入,暫時(shí)沒有發(fā)現(xiàn)這種問題(讀這個(gè)源碼的朋友如果能改進(jìn)這個(gè)錯(cuò)誤請(qǐng)私信我,萬(wàn)分感謝?。。。?/em>*/
@property (nonatomic, strong) NSMutableArray *placeTextDataSource; // 替換匹配字段
@property (nonatomic, strong) NSString *judgeStr; // 用來(lái)判斷展示的table
@property (nonatomic, strong) SearchModel *model;
// 輸入顯示字段
@property (nonatomic, strong) NSString *textFieldStr;
@end
</pre>
我們要通過textField的代理事件來(lái)實(shí)現(xiàn)搜索的交互事件
<pre>
pragma mark --- TextFieldDelegate
/**
- 點(diǎn)擊鍵盤搜索按鈕
*/
-
(BOOL)textFieldShouldReturn:(UITextField *)textField
{
// 收起鍵盤
[_searchTextField resignFirstResponder];
// 移除tableView
[_myTable removeFromSuperview];
// 先清空數(shù)據(jù)源,然后請(qǐng)求數(shù)據(jù)
[self.dataSource removeAllObjects];
[self getDataByText:textField.text];// 存入搜索歷史
_model.historyStr = textField.text;
if (textField.text.length>0) {
if (![[DataBase shareDataBase] isHadSaveModel:_model]) {
[[DataBase shareDataBase] saveModel:_model];
}
}
return YES;
}
/**
- 點(diǎn)擊輸入框開始編輯時(shí)走這個(gè)方法。 (我們需要點(diǎn)擊輸入框時(shí),在輸入框下面出現(xiàn)一
- 個(gè)tableView來(lái)展示搜索的歷史記錄)
*/
-
(void)textFieldDidBeginEditing:(UITextField *)textField
{// 先移除之前添加上的tableView
[self.myTable removeFromSuperview];
// 再次添加
self.judgeStr = History;
[self creatTableViewWithStr:self.judgeStr];// 打開輸入框后,展示搜索歷史記錄
self.historyDataSource = [NSMutableArray arrayWithArray:[[DataBase shareDataBase] selectAllModel]];
[self.myTable reloadData];
}
/**
- 當(dāng)我們開始編輯時(shí),根據(jù)我們當(dāng)前輸入的字段進(jìn)行匹配關(guān)鍵字,需要用到這個(gè)方法。 這個(gè)方法
- 是當(dāng)輸入框內(nèi)容開始發(fā)生變化時(shí)調(diào)用
*/
-
(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{// 輸入時(shí)開始匹配關(guān)鍵字,顯示另一個(gè)tableView
// 先移除之前添加上的tableView
[self.myTable removeFromSuperview];
// 再次添加
self.judgeStr = keyWord;
[self creatTableViewWithStr:self.judgeStr];self.textFieldStr = string;
// 請(qǐng)求匹配關(guān)鍵字
// 先清空保存的數(shù)據(jù)
[self.textFieldDataSource removeAllObjects];
[self getDataByTextfieldText:self.textFieldStr];return YES;
}
</pre>
代碼有點(diǎn)多,不明白的同學(xué)可以到我的git主頁(yè)上下載源碼,里面注釋寫的也比較詳細(xì)
git:https://github.com/you12138/SearchLikeWangYiMusic.git